{"id":476555,"date":"2026-04-19T13:46:18","date_gmt":"2026-04-19T13:46:18","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=476555"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=476555","title":{"rendered":"ICMP-\u0442\u0443\u043d\u043d\u0435\u043b\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u044f\u0434\u0440\u0430 Linux: \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c TCP\/UDP-\u0442\u0440\u0430\u0444\u0438\u043a \u0447\u0435\u0440\u0435\u0437 \u044d\u0445\u043e-\u0437\u0430\u043f\u0440\u043e\u0441\u044b"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f <a href=\"https:\/\/habr.com\/ru\/companies\/ruvds\/articles\/516266\/\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044e \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 ICMP-\u043f\u0430\u043a\u0435\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/a>. \u0421\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043c\u044b\u0441\u043b\u044c: \u0430 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0433\u043d\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0442\u0440\u0430\u0444\u0438\u043a \u0447\u0435\u0440\u0435\u0437 ICMP (\u0434\u0430, \u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0438 ICMP-\u0442\u0443\u043d\u043d\u0435\u043b\u044f \u044f \u0442\u043e\u0436\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u043b). \u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442 \u2014 ICMP-\u0442\u0443\u043d\u043d\u0435\u043b\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u044f\u0434\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439:<\/p>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 TCP\/UDP-\u043f\u0430\u043a\u0435\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u0438\u0445 \u0432 ICMP \u044d\u0445\u043e-\u0437\u0430\u043f\u0440\u043e\u0441\u044b (\u0442\u0438\u043f ICMP_ECHO);<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430 \u043f\u0440\u0438\u0451\u043c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0438\u0445 \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0426\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u2014 \u0443\u0433\u043b\u0443\u0431\u0438\u0442\u044c \u0437\u043d\u0430\u043d\u0438\u044f \u0432:<\/p>\n<ul>\n<li>\n<p>\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u044f\u0434\u0440\u0430 (\u0440\u0430\u0431\u043e\u0442\u0430 \u0441 sk_buff, \u0445\u0443\u043a\u0438 Netfilter, \u0442\u0430\u0441\u043a\u043b\u0435\u0442\u044b). \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 Linux \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 user space;<\/p>\n<\/li>\n<li>\n<p>\u0441\u0435\u0442\u0435\u0432\u043e\u043c \u0441\u0442\u0435\u043a\u0435 (IPv4, Ethernet, ICMP, TCP, UDP) \u0438, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 Linux. \u0414\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0441\u0435\u0442\u0435\u0432\u044b\u043c\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u043b\u0430\u0441\u044c \u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430\u0445 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u0430\u043a\u0435\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<ol>\n<li>\n<p>\u0425\u0443\u043a <code>NF_INET_POST_ROUTING<\/code> &#8212; \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043a\u0438\u043d\u0443\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e user space \u0438 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u043e \u0441\u0435\u0442\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443:<\/p>\n<ol>\n<li>\n<p>\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442 TCP\/UDP-\u0442\u0440\u0430\u0444\u0438\u043a;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 \u0432 ICMP. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u0430\u043a\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cd8\/299\/4bf\/cd82994bff6c1fa3d67bbc4c2aa70d5c.png\" alt=\"Packet\" title=\"\u041f\u0430\u043a\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"421\" height=\"351\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cd8\/299\/4bf\/cd82994bff6c1fa3d67bbc4c2aa70d5c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cd8\/299\/4bf\/cd82994bff6c1fa3d67bbc4c2aa70d5c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0430\u043a\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0445<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>\u0425\u0443\u043a <code>NF_INET_LOCAL_IN<\/code> &#8212; \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0448\u043b\u0438 \u0432\u0441\u0435 \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0432 user space:<\/p>\n<ol>\n<li>\n<p>\u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 ICMP-\u043f\u0430\u043a\u0435\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 TCP\/UDP-\u043f\u0430\u043a\u0435\u0442;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 loopback-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 (lo) \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439.<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p>\u0422\u0430\u0441\u043a\u043b\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0428\u0430\u0433 1. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0445\u0443\u043a\u043e\u0432<\/h3>\n<pre><code class=\"cpp\">inputHook.hook = input_hook;inputHook.hooknum = NF_INET_LOCAL_IN;inputHook.pf = PF_INET;inputHook.priority = NF_IP_PRI_FIRST;nf_register_net_hook(&amp;init_net, &amp;inputHook);outputHook.hook = output_hook;outputHook.hooknum = NF_INET_POST_ROUTING;outputHook.pf = PF_INET;outputHook.priority = NF_IP_PRI_FIRST;nf_register_net_hook(&amp;init_net, &amp;outputHook);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p><code>NF_INET_POST_ROUTING<\/code> \u2014 \u0445\u0443\u043a \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430;<\/p>\n<\/li>\n<li>\n<p><code>NF_INET_LOCAL_IN<\/code> \u2014 \u0445\u0443\u043a \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442  <code>NF_IP_PRI_FIRST<\/code> \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u043c.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0428\u0430\u0433 2. \u0417\u0430\u0434\u0430\u0447\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/h3>\n<pre><code class=\"cpp\">struct task_data {    struct tasklet_struct tasklet;    struct sk_buff *skb;};void send_func (unsigned long d){    struct task_data *data = (struct task_data *)d;    if (dev_queue_xmit(data-&gt;skb) != 0)     {        pr_err(\"dev_queue_xmit failed\\n\");        kfree_skb(data-&gt;skb);    }    kfree (data);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0442\u0430\u0441\u043a\u043b\u0435\u0442\u044b. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043d\u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 (<a href=\"https:\/\/habr.com\/ru\/companies\/embox\/articles\/244071\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/companies\/embox\/articles\/244071\/<\/a>).<\/p>\n<\/li>\n<li>\n<p><code>sk_buff<\/code> &#8212; \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0435\u0442\u0435\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0432 \u044f\u0434\u0440\u0435 Linux.<\/p>\n<\/li>\n<li>\n<p><code>dev_queue_xmit<\/code> &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0442\u0430\u0432\u0438\u0442 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0431\u0443\u0444\u0435\u0440 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0443\u0434\u0430\u0447\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u0430 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0430\u0435\u043c sk_buff \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0430  <code>kfree_skb(data-&gt;skb);<\/code><\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c, \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0443 <code>kfree (data)<\/code><\/p>\n<\/li>\n<\/ul>\n<h3>\u0428\u0430\u0433 3. \u0425\u0443\u043a NF_INET_POST_ROUTING<\/h3>\n<pre><code class=\"cpp\">static unsigned int output_hook (void *priv, struct sk_buff *skb, const struct nf_hook_state *state){    struct sk_buff *skb_out = create_packet_output (skb);    if (!skb_out)        return NF_ACCEPT;        struct task_data *data = kmalloc (sizeof(struct task_data), GFP_ATOMIC);    if (!data)    {        pr_err(\"kmalloc\\n\");        kfree_skb(skb_out);        return NF_ACCEPT;    }    data-&gt;skb = skb_out;    tasklet_init (&amp;data-&gt;tasklet, send_func, (unsigned long)data);    tasklet_schedule (&amp;data-&gt;tasklet);    return NF_STOLEN;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>create_packet_output<\/code>; <\/p>\n<ul>\n<li>\n<p>\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442 TCP\/UDP \u043f\u0430\u043a\u0435\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 TCP\/UDP \u043f\u0430\u043a\u0435\u0442 \u0432 ICMP;<\/p>\n<\/li>\n<li>\n<p>\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 <code>sk_buff<\/code> \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0430\u043a\u0435\u0442 \u043d\u0435 \u043f\u0440\u043e\u0448\u0451\u043b \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u0438\u043b\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c  <code>sk_buff<\/code> , \u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0430\u043a\u0435\u0442 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>NF_ACCEPT<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0442\u0430\u0441\u043a\u043b\u0435\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443: <code>tasklet_schedule (&amp;data-&gt;tasklet)<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>NF_STOLEN<\/code> &#8212; \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u044f\u0434\u0440\u0443, \u0447\u0442\u043e \u043f\u0430\u043a\u0435\u0442 \u043c\u044b \u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e. \u0412\u0430\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e, \u0430 \u043d\u0435 <code>NF_DROP<\/code>.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 create_packet_output<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">static struct sk_buff* create_packet_output(struct sk_buff* in_packet){       struct iphdr* ip_in = ip_hdr(in_packet);   uint8_t mac_out[ETH_ALEN];   uint8_t protocol_type;   uint16_t header_len;   void* transport_hdr;   uint16_t data_len;      if (ip_in-&gt;protocol != IPPROTO_UDP &amp;&amp; ip_in-&gt;protocol != IPPROTO_TCP)    {       return NULL;   }      if (find_mac_addr(mac_out, ip_in-&gt;daddr, in_packet-&gt;dev) &lt; 0)    {       pr_info(\"Not found mac\\n\");       return NULL;   }      if (skb_linearize(in_packet))    {       pr_info(\"Failed to linearize skb\\n\");       return NULL;   }      if (ip_in-&gt;protocol == IPPROTO_UDP)    {       struct udphdr* in_udp = udp_hdr(in_packet);       protocol_type = 0;         header_len = sizeof(struct udphdr);       transport_hdr = in_udp;       data_len = ntohs(in_udp-&gt;len) - sizeof(struct udphdr);   }    else    {        struct tcphdr* in_tcp = tcp_hdr(in_packet);       protocol_type = 1;         header_len = tcp_hdrlen(in_packet);       transport_hdr = in_tcp;       data_len = ntohs(ip_in-&gt;tot_len) - (ip_in-&gt;ihl * 4) - header_len;   }      int packet_size = sizeof(struct ethhdr)                    + sizeof(struct iphdr)                    + sizeof(struct icmphdr)                   + header_len                   + data_len;      int hh_len = LL_RESERVED_SPACE(in_packet-&gt;dev);   int tlen = in_packet-&gt;dev-&gt;needed_tailroom;   struct sk_buff* skb = netdev_alloc_skb(in_packet-&gt;dev, hh_len + tlen + packet_size);   if (unlikely(!skb))    {       pr_err(\"netdev_alloc_skb failed\\n\");       return NULL;   }      skb_reserve(skb, hh_len);   skb-&gt;dev = in_packet-&gt;dev;   skb-&gt;protocol = htons(ETH_P_IP);   skb_put(skb, packet_size);   skb_reset_network_header(skb);   skb_set_transport_header(skb, sizeof(struct iphdr));      struct iphdr* ip_out = ip_hdr(skb);   ip_out-&gt;version = 4;   ip_out-&gt;ihl = 5;   ip_out-&gt;tos = 0;   ip_out-&gt;tot_len = htons(packet_size - sizeof(struct ethhdr));   ip_out-&gt;id = 0;   ip_out-&gt;frag_off = htons(0x4000);   ip_out-&gt;ttl = 64;   ip_out-&gt;protocol = IPPROTO_ICMP;   ip_out-&gt;saddr = ip_in-&gt;saddr;   ip_out-&gt;daddr = ip_in-&gt;daddr;   ip_out-&gt;check = 0;   ip_out-&gt;check = ip_fast_csum((u8 *)ip_out, ip_out-&gt;ihl);      struct transfer_header header;   static uint8_t id = 0;   header.id = id++;   header.last = 1;   header.type = protocol_type;      struct icmphdr* icmp = icmp_hdr(skb);   icmp-&gt;type = ICMP_ECHO;   icmp-&gt;code = 0;   icmp-&gt;checksum = 0;   icmp-&gt;un.echo.id = htons(*(uint16_t*)&amp;header);   icmp-&gt;un.echo.sequence = 1;      uint8_t* data_out = (uint8_t*)(icmp + 1);   memcpy(data_out, transport_hdr, header_len);   data_out += header_len;      uint8_t* data_in = (uint8_t*)transport_hdr + header_len;   memcpy(data_out, data_in, data_len);      icmp-&gt;checksum = ip_compute_csum(icmp, sizeof(struct icmphdr) + header_len + data_len);      skb_push(skb, sizeof(struct ethhdr));   skb_reset_mac_header(skb);      struct ethhdr *eth_out = eth_hdr(skb);   memset(eth_out, 0, sizeof(struct ethhdr));   memcpy(eth_out-&gt;h_source, skb-&gt;dev-&gt;dev_addr, ETH_ALEN);   memcpy(eth_out-&gt;h_dest, mac_out, ETH_ALEN);   eth_out-&gt;h_proto = htons(0x0800);      return skb;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<h4>\u0428\u0430\u0433 3.1. \u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f TCP\/UDP \u043f\u0430\u043a\u0435\u0442\u044b<\/h4>\n<pre><code class=\"cpp\">struct iphdr* ip_in = ip_hdr(in_packet);if (ip_in-&gt;protocol != IPPROTO_UDP &amp;&amp; ip_in-&gt;protocol != IPPROTO_TCP) {    return NULL;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f. \u0414\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u0438 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f IPv4. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>ip_hdr<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430 \u0442\u0438\u043f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0432 IPv4 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u0435 protocol. \u0414\u043b\u044f TCP \u043e\u043d\u043e \u0440\u0430\u0432\u043d\u043e 6, \u0434\u043b\u044f UDP \u2014 17, \u0434\u043b\u044f ICMP \u2014 1.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 3.2. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435  sk_buff<\/h4>\n<pre><code class=\"cpp\">if (ip_in-&gt;protocol == IPPROTO_UDP) {    struct udphdr* in_udp = udp_hdr(in_packet);    protocol_type = 0;      header_len = sizeof(struct udphdr);    transport_hdr = in_udp;    data_len = ntohs(in_udp-&gt;len) - sizeof(struct udphdr);} else {     struct tcphdr* in_tcp = tcp_hdr(in_packet);    protocol_type = 1;      header_len = tcp_hdrlen(in_packet);    transport_hdr = in_tcp;    data_len = ntohs(ip_in-&gt;tot_len) - (ip_in-&gt;ihl * 4) - header_len;}int packet_size = sizeof(struct ethhdr)                     + sizeof(struct iphdr)                     + sizeof(struct icmphdr)                    + header_len                    + data_len;    int hh_len = LL_RESERVED_SPACE(in_packet-&gt;dev);int tlen = in_packet-&gt;dev-&gt;needed_tailroom;struct sk_buff* skb = netdev_alloc_skb(in_packet-&gt;dev, hh_len + tlen + packet_size);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430: <code>header_len = sizeof(struct udphdr);<\/code> \/ <code> header_len = tcp_hdrlen(in_packet);<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:  <code>data_len = ntohs(in_udp-&gt;len) - sizeof(struct udphdr);<\/code> \/<code>data_len = ntohs(ip_in-&gt;tot_len) - (ip_in-&gt;ihl * 4) - header_len; <\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: <code>sizeof(struct ethhdr) <\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: <code>sizeof(struct iphdr)<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f:<code>sizeof(struct icmphdr)<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u043f\u043e\u0434 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435: <code>header_len + data_len<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u043f\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>LL_RESERVED_SPACE(in_packet-&gt;dev)<\/code>, <code>in_packet-&gt;dev-&gt;needed_tailroom<\/code><\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 3.3. \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043a\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f<\/h4>\n<pre><code class=\"cpp\">static int find_mac_addr (uint8_t* mac, uint32_t ip, struct net_device *dev){    struct neighbour *neigh = __ipv4_neigh_lookup(dev, ip);    if (neigh &amp;&amp; (neigh-&gt;nud_state &amp; NUD_VALID))     {        memcpy(mac, neigh-&gt;ha, ETH_ALEN);        neigh_release(neigh);        return 0;    }    return -1;}skb_push(skb, sizeof(struct ethhdr));skb_reset_mac_header(skb);struct ethhdr *eth_out = eth_hdr(skb);memset(eth_out, 0, sizeof(struct ethhdr));memcpy(eth_out-&gt;h_source, skb-&gt;dev-&gt;dev_addr, ETH_ALEN);memcpy(eth_out-&gt;h_dest, mac_out, ETH_ALEN);eth_out-&gt;h_proto = htons(0x0800);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u0438\u0437 user space \u0443 \u043d\u0430\u0441 \u0435\u0449\u0451 \u043d\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043a\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f, \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><code>skb-&gt;dev-&gt;dev_addr<\/code> &#8212; \u043d\u0430\u0448 MAC-\u0430\u0434\u0440\u0435\u0441.<\/p>\n<\/li>\n<li>\n<p><code>find_mac_addr<\/code> &#8212; \u043f\u043e\u0438\u0441\u043a MAC-\u0430\u0434\u0440\u0435\u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0435\u0433\u043e IP-\u0430\u0434\u0440\u0435\u0441\u0443.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 3.4. \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f<\/h4>\n<pre><code class=\"cpp\">skb_reset_network_header(skb);skb_set_transport_header(skb, sizeof(struct iphdr));struct iphdr* ip_out = ip_hdr(skb);ip_out-&gt;version = 4;ip_out-&gt;ihl = 5;ip_out-&gt;tos = 0;ip_out-&gt;tot_len = htons(packet_size - sizeof(struct ethhdr));ip_out-&gt;id = 0;ip_out-&gt;frag_off = htons(0x4000);ip_out-&gt;ttl = 64;ip_out-&gt;protocol = IPPROTO_ICMP;ip_out-&gt;saddr = ip_in-&gt;saddr;ip_out-&gt;daddr = ip_in-&gt;daddr;ip_out-&gt;check = 0;ip_out-&gt;check = ip_fast_csum((u8 *)ip_out, ip_out-&gt;ihl);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c ICMP.<\/p>\n<\/li>\n<li>\n<p><code>ip_out-&gt;version = 4<\/code> &#8212; \u0412\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430<\/p>\n<\/li>\n<li>\n<p><code>ip_out-&gt;ihl  = 5<\/code> &#8212; \u0414\u043b\u0438\u043d\u043d\u0430 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u043c\u0430\u044f \u0432 32-\u0431\u0438\u0442\u043d\u044b\u0445 \u0441\u043b\u043e\u0432\u0430\u0445<\/p>\n<\/li>\n<li>\n<p><code>ip_out-&gt;ttl = 64<\/code> &#8212; \u0412\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u043f\u0430\u043a\u0442\u0435<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 3.5. \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c ICMP \u043f\u0430\u043a\u0435\u0442<\/h4>\n<pre><code class=\"cpp\">struct icmphdr* icmp = icmp_hdr(skb);icmp-&gt;type = ICMP_ECHO;icmp-&gt;code = 0;icmp-&gt;checksum = 0;struct transfer_header{    uint8_t id;    uint8_t last : 1;    uint8_t type : 3;    uint8_t reserv : 4;};    static uint8_t id = 0;header.id = id++;header.last = 1;header.type = protocol_type;icmp-&gt;un.echo.id = htons(*(uint16_t*)&amp;header);icmp-&gt;un.echo.sequence = 1;memcpy(data_out, transport_hdr, header_len);data_out += header_len;uint8_t* data_in = (uint8_t*)transport_hdr + header_len;memcpy(data_out, data_in, data_len);icmp-&gt;checksum = ip_compute_csum(icmp, sizeof(struct icmphdr) + header_len + data_len);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c ECHO-\u0437\u0430\u043f\u0440\u043e\u0441:  <code>icmp-&gt;type = ICMP_ECHO<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043f\u0430\u043a\u0435\u0442\u0430\u0445 echo-\u0437\u0430\u043f\u0440\u043e\u0441 \u0438 echo-\u043e\u0442\u0432\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0432\u0430 16-\u0431\u0438\u0442\u043d\u044b\u0445 \u0441\u043b\u043e\u0432\u0430. \u0412 \u043f\u043e\u043b\u0435 sequence \u0445\u0440\u0430\u043d\u0438\u043c \u043d\u043e\u043c\u0435\u0440 \u0444\u0440\u0435\u0439\u043c\u0430, \u0430 \u0432 \u043f\u043e\u043b\u0435 id \u0445\u0440\u0430\u043d\u0438\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0441\u0435\u0432\u0434\u043e\u043f\u0430\u043a\u0435\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430\u044f \u0441\u0443\u043c\u043c\u0430 \u0434\u043b\u044f ICMP \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0428\u0430\u0433 4. \u0425\u0443\u043a NF_INET_LOCAL_IN<\/h3>\n<pre><code class=\"cpp\">static unsigned int input_hook (void *priv, struct sk_buff *skb, const struct nf_hook_state *state){    struct iphdr *iph = ip_hdr(skb);    if (iph-&gt;protocol != IPPROTO_ICMP)        return NF_ACCEPT;    struct icmphdr *icmph = icmp_hdr(skb);       if (icmph-&gt;type != ICMP_ECHO)        return NF_ACCEPT;    struct sk_buff *skb_out = create_packet_input (skb);    if (!skb_out)        return NF_ACCEPT;    struct task_data *data = kmalloc(sizeof(struct task_data), GFP_ATOMIC);    if (!data)    {        pr_err(\"kmalloc\\n\");        kfree_skb(skb_out);        return NF_ACCEPT;    }    data-&gt;skb = skb_out;    tasklet_init(&amp;data-&gt;tasklet, send_func, (unsigned long)data);    tasklet_schedule(&amp;data-&gt;tasklet);        return NF_STOLEN;    }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0424\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u043f\u0430\u043a\u0435\u0442\u044b, \u043a\u0440\u043e\u043c\u0435 ICMP.<\/p>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c  <code>sk_buff<\/code> \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 lo.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0428\u0430\u0433 4.1. \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u0430\u043a\u0435\u0442 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 lo<\/h3>\n<pre><code class=\"cpp\">struct net_device *dev = dev_get_by_name(&amp;init_net, \"lo\");<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 create_packet_input<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">   static struct sk_buff* create_packet_input(struct sk_buff* in_packet){       struct iphdr* ip_in = ip_hdr(in_packet);   struct icmphdr* icmp_in = icmp_hdr(in_packet);      uint16_t id = ntohs(icmp_in-&gt;un.echo.id);   struct transfer_header* header = (struct transfer_header*)&amp;id;      if (header-&gt;type != 0 &amp;&amp; header-&gt;type != 1)    {       pr_err(\"Unknown protocol type: %d\\n\", header-&gt;type);       return NULL;   }      struct net_device *dev = dev_get_by_name(&amp;init_net, \"lo\");   if (!dev)    {       pr_err(\"Cannot get loopback device\\n\");       return NULL;   }      uint8_t mac_in[ETH_ALEN];   if (find_mac_addr(mac_in, ip_in-&gt;saddr, in_packet-&gt;dev) &lt; 0)   {       pr_info(\"MAC address not found for %pI4\\n\", &amp;ip_in-&gt;saddr);       return NULL;   }      uint8_t* data_in = (uint8_t*)(icmp_in + 1);   void* transport_in;   uint32_t transport_header_len;   uint16_t data_len;   uint8_t protocol;      if (header-&gt;type == 0)    {         struct udphdr* udp_in = (struct udphdr*)data_in;       transport_in = udp_in;       transport_header_len = sizeof(struct udphdr);       data_len = (uint8_t*)skb_tail_pointer(in_packet)                   - (uint8_t*)icmp_in                   - sizeof(struct icmphdr)                   - sizeof(struct udphdr);       protocol = IPPROTO_UDP;   }    else    {         struct tcphdr* tcp_in = (struct tcphdr*)data_in;       transport_in = tcp_in;       transport_header_len = __tcp_hdrlen(tcp_in);       data_len = (uint8_t*)skb_tail_pointer(in_packet)                   - (uint8_t*)icmp_in                   - sizeof(struct icmphdr)                   - transport_header_len;       protocol = IPPROTO_TCP;   }      int packet_size = sizeof(struct ethhdr)                    + sizeof(struct iphdr)                    + transport_header_len                   + data_len;      int hh_len = LL_RESERVED_SPACE(dev);   int tlen = dev-&gt;needed_tailroom;   struct sk_buff* skb = netdev_alloc_skb(dev, hh_len + tlen + packet_size);   if (unlikely(!skb)) {       pr_err(\"netdev_alloc_skb failed\\n\");       return NULL;   }      skb_reserve(skb, hh_len);   skb-&gt;dev = dev;   skb-&gt;protocol = htons(ETH_P_IP);   skb_put(skb, packet_size);   skb_reset_network_header(skb);   skb_set_transport_header(skb, sizeof(struct iphdr));      struct iphdr* ip_out = ip_hdr(skb);   ip_out-&gt;version = 4;   ip_out-&gt;ihl = 5;   ip_out-&gt;tos = 0;   ip_out-&gt;tot_len = htons(packet_size - sizeof(struct ethhdr));   ip_out-&gt;id = 0;   ip_out-&gt;frag_off = htons(0x4000);   ip_out-&gt;ttl = 64;   ip_out-&gt;protocol = protocol;   ip_out-&gt;saddr = ip_in-&gt;saddr;   ip_out-&gt;daddr = ip_in-&gt;daddr;   ip_out-&gt;check = 0;   ip_out-&gt;check = ip_fast_csum((u8 *)ip_out, ip_out-&gt;ihl);      if (protocol == IPPROTO_UDP)    {       struct udphdr* udph = udp_hdr(skb);       struct udphdr* udp_in = (struct udphdr*)transport_in;              udph-&gt;source = udp_in-&gt;source;       udph-&gt;dest = udp_in-&gt;dest;       udph-&gt;len = udp_in-&gt;len;       udph-&gt;check = 0;              uint8_t* data_out = (uint8_t*)(udph + 1);       memcpy(data_out, data_in + sizeof(struct udphdr), data_len);          }    else    {         struct tcphdr* tcph = tcp_hdr(skb);       struct tcphdr* tcp_in = (struct tcphdr*)transport_in;              memcpy(tcph, tcp_in, transport_header_len);       tcph-&gt;check = 0;              uint8_t* data_out = (uint8_t*)tcph + transport_header_len;       memcpy(data_out, data_in + transport_header_len, data_len);              int tcplen = transport_header_len + data_len;       tcph-&gt;check = tcp_v4_check(tcplen,                                    ip_out-&gt;saddr,                                    ip_out-&gt;daddr,                                    csum_partial((char *)tcph, tcplen, 0));       skb-&gt;ip_summed = CHECKSUM_NONE;   }      skb_push(skb, sizeof(struct ethhdr));   skb_reset_mac_header(skb);      struct ethhdr *eth_out = eth_hdr(skb);   memset(eth_out, 0, sizeof(struct ethhdr));   memcpy(eth_out-&gt;h_source, mac_in, ETH_ALEN);   memcpy(eth_out-&gt;h_dest, dev-&gt;dev_addr, ETH_ALEN);   eth_out-&gt;h_proto = htons(ETH_P_IP);      return skb;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<h2>\u0428\u0430\u0433 5. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c<\/h2>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c 2 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0438\u0445 \u0432 \u043e\u0431\u0449\u0443\u044e \u0441\u0435\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b VirtualBox.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u0435\u0440\u0451\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u0434 \u043d\u0430\u0448\u0443 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b <code>ismod<\/code> \u043d\u0430 \u043e\u0431\u0435\u0438\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u0438\u0451\u043c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">nc -ul 4020  # \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c UDP-\u043f\u0430\u043a\u0435\u0442\u044b \u043d\u0430 4020 \u043f\u043e\u0440\u0442tcpdump -I enp0s3 \u2013 w captureEnp.pcap # \u0417\u0430\u043f\u0438\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 enp0s3 (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u043d\u0430\u0448\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0448\u0438\u043d\u044b)tcpdump -I lo \u2013 w captureLo.pcap  <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<li>\n<p>\u041d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u0432\u0432\u043e\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0438 \u0432\u0432\u043e\u0434\u0438\u043c \u0442\u0435\u043a\u0441\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:<\/p>\n<pre><code class=\"bash\">nc \u2013 u ip 4020 <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u0438\u0451\u043c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435: <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3f0\/881\/d55\/3f0881d55c0882d7e2c42bdb14dc6268.png\" alt=\"messeger\" title=\"\" width=\"974\" height=\"413\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/3f0\/881\/d55\/3f0881d55c0882d7e2c42bdb14dc6268.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3f0\/881\/d55\/3f0881d55c0882d7e2c42bdb14dc6268.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b captureEnp.pcap \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Wireshark \u0438 \u0432\u0438\u0434\u0438\u043c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c Hello, \u0437\u0430\u0432\u0451\u0440\u043d\u0443\u0442\u043e\u0435 \u0432 ICMP-\u043f\u0430\u043a\u0435\u0442: <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8bb\/0e1\/591\/8bb0e1591f82bcc1b95f69eee4a7647e.JPG\" alt=\"icmp1\" title=\"ICMP-\u041f\u0430\u043a\u0435\u0442\u044b\" width=\"2113\" height=\"1386\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/8bb\/0e1\/591\/8bb0e1591f82bcc1b95f69eee4a7647e.JPG 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8bb\/0e1\/591\/8bb0e1591f82bcc1b95f69eee4a7647e.JPG 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>ICMP-\u041f\u0430\u043a\u0435\u0442\u044b<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b captureLo.pcap \u0438 \u0432\u0438\u0434\u0438\u043c \u0443\u0436\u0435 UDP-\u043f\u0430\u043a\u0435\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0434\u0443\u0442 \u043a \u043d\u0430\u043c: <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d33\/b82\/e65\/d33b82e65d0335aaf2d19784ccfec67e.JPG\" alt=\"udp1\" title=\"UDP-\u043f\u0430\u043a\u0435\u0442\u044b\" width=\"2282\" height=\"1366\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d33\/b82\/e65\/d33b82e65d0335aaf2d19784ccfec67e.JPG 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d33\/b82\/e65\/d33b82e65d0335aaf2d19784ccfec67e.JPG 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>UDP-\u043f\u0430\u043a\u0435\u0442\u044b<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<\/ol>\n<h2>\u0428\u0430\u0433 6. \u0424\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c UDP \u0438 TCP-\u043f\u0430\u043a\u0435\u0442\u044b \u0447\u0435\u0440\u0435\u0437 ICMP-\u0442\u0443\u043d\u043d\u0435\u043b\u044c. \u041d\u043e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u043b\u0438\u043d\u0430 ICMP-\u043f\u0430\u043a\u0435\u0442\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u0434\u043b\u0438\u043d\u043e\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430, \u0447\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432.<\/p>\n<h4>\u0428\u0430\u0433 6.1 \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0434\u0443\u043b\u044f<\/h4>\n<pre><code class=\"cpp\">static int max_size = 10; module_param(max_size, int, 0644);MODULE_PARM_DESC(my_int, \"Max size out packet\");<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>\u0428\u0430\u0433 6.2 \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/h4>\n<ol>\n<li>\n<p>\u0420\u0430\u0441\u0447\u0451\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f ICMP-\u043f\u0430\u043a\u0435\u0442\u0430 (\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a + \u0434\u0430\u043d\u043d\u044b\u0435):<\/p>\n<pre><code class=\"cpp\">if (ip_in-&gt;protocol == IPPROTO_UDP) {    struct udphdr* in_udp = udp_hdr(in_packet);    protocol_type = 0;      data_in = (uint8_t*)in_udp;    data_len = ntohs(in_udp-&gt;len);} else {     struct tcphdr* in_tcp = tcp_hdr(in_packet);    protocol_type = 1;      data_in = (uint8_t*)in_tcp;    data_len =  ntohs(ip_in-&gt;tot_len) - (ip_in-&gt;ihl * 4);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<li>\n<p>\u041d\u0430\u0440\u0435\u0437\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u0430 \u043d\u0430 \u043f\u043e\u0434\u043f\u0430\u043a\u0435\u0442\u044b:<\/p>\n<pre><code class=\"cpp\">int packet_len = (data_len&gt;max_size)?max_size:data_len;data_len -= packet_len;int packet_size = sizeof(struct ethhdr)             + sizeof(struct iphdr)             + sizeof(struct icmphdr)            + packet_len;struct sk_buff* skb = netdev_alloc_skb(in_packet-&gt;dev, hh_len + tlen + packet_size);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 <code>sk_buff<\/code> \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438:<\/p>\n<pre><code class=\"cpp\">if (!skb_out){    skb_out = skb;}if (skb_current){    skb_current-&gt;next = skb;    skb-&gt;prev = skb_current;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u0430. <code>id<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435. \u0412 \u043f\u043e\u043b\u0435  <code>last<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u0438\u0437\u043d\u0430\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430. \u0412 <code>icmp-&gt;un.echo.sequence<\/code> \u2014 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0434\u043f\u0430\u043a\u0435\u0442\u0430.<\/p>\n<pre><code class=\"cpp\">header.id = id;header.last = (data_len == 0)?1:0;header.type = protocol_type;header.reserv = 0;icmp-&gt;un.echo.sequence = htons(frag++);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0430\u043a\u0435\u0442\u0435<\/p>\n<pre><code class=\"cpp\">uint8_t* data_out = (uint8_t*)(icmp + 1);memcpy(data_out, data_in, packet_len);icmp-&gt;checksum = ip_compute_csum(icmp, sizeof(struct icmphdr) + packet_len);    data_in += packet_len;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 create_packet_input \u0441 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cpp\">static struct sk_buff* create_packet_output(struct sk_buff* in_packet){       struct iphdr* ip_in = ip_hdr(in_packet);   uint8_t mac_out[ETH_ALEN];   uint8_t protocol_type;   uint16_t data_len;   uint8_t* data_in;      if (ip_in-&gt;protocol != IPPROTO_UDP &amp;&amp; ip_in-&gt;protocol != IPPROTO_TCP)    {       return NULL;   }      if (find_mac_addr(mac_out, ip_in-&gt;daddr, in_packet-&gt;dev) &lt; 0)    {       pr_info(\"Not found mac\\n\");       return NULL;   }      if (skb_linearize(in_packet))    {       pr_info(\"Failed to linearize skb\\n\");       return NULL;   }      if (ip_in-&gt;protocol == IPPROTO_UDP)    {       struct udphdr* in_udp = udp_hdr(in_packet);       protocol_type = 0;         data_in = (uint8_t*)in_udp;       data_len = ntohs(in_udp-&gt;len);   }    else    {        struct tcphdr* in_tcp = tcp_hdr(in_packet);       protocol_type = 1;         data_in = (uint8_t*)in_tcp;       data_len =  ntohs(ip_in-&gt;tot_len) - (ip_in-&gt;ihl * 4);   }   static uint8_t id = 0;   id++;      int hh_len = LL_RESERVED_SPACE(in_packet-&gt;dev);   int tlen = in_packet-&gt;dev-&gt;needed_tailroom;   struct sk_buff* skb_out = NULL;   struct sk_buff* skb_current = NULL;   uint16_t frag = 0;   while(true)   {       int packet_len = (data_len&gt;max_size)?max_size:data_len;       data_len -= packet_len;       int packet_size = sizeof(struct ethhdr)                    + sizeof(struct iphdr)                    + sizeof(struct icmphdr)                   + packet_len;       struct sk_buff* skb = netdev_alloc_skb(in_packet-&gt;dev, hh_len + tlen + packet_size);              if (!skb)        {           while (skb_out)           {               skb = skb_out-&gt;next;               kfree_skb(skb_out);               skb_out = skb;           }           pr_err(\"netdev_alloc_skb failed\\n\");           return NULL;       }       if (!skb_out)       {           skb_out = skb;       }       if (skb_current)       {           skb_current-&gt;next = skb;           skb-&gt;prev = skb_current;       }              skb_reserve(skb, hh_len);       skb-&gt;dev = in_packet-&gt;dev;       skb-&gt;protocol = htons(ETH_P_IP);       skb_put(skb, packet_size);       skb_reset_network_header(skb);       skb_set_transport_header(skb, sizeof(struct iphdr));              struct iphdr* ip_out = ip_hdr(skb);       ip_out-&gt;version = 4;       ip_out-&gt;ihl = 5;       ip_out-&gt;tos = 0;       ip_out-&gt;tot_len = htons(packet_size - sizeof(struct ethhdr));       ip_out-&gt;id = 0;       ip_out-&gt;frag_off = htons(0x4000);       ip_out-&gt;ttl = 64;       ip_out-&gt;protocol = IPPROTO_ICMP;       ip_out-&gt;saddr = ip_in-&gt;saddr;       ip_out-&gt;daddr = ip_in-&gt;daddr;       ip_out-&gt;check = 0;       ip_out-&gt;check = ip_fast_csum((u8 *)ip_out, ip_out-&gt;ihl);              struct transfer_header header;       header.id = id;       header.last = (data_len == 0)?1:0;       header.type = protocol_type;       header.reserv = 0;              struct icmphdr* icmp = icmp_hdr(skb);       icmp-&gt;type = ICMP_ECHOREPLY;       icmp-&gt;code = 0;       icmp-&gt;checksum = 0;       icmp-&gt;un.echo.id = htons(*(uint16_t*)&amp;header);       icmp-&gt;un.echo.sequence = htons(frag++);              uint8_t* data_out = (uint8_t*)(icmp + 1);       memcpy(data_out, data_in, packet_len);              icmp-&gt;checksum = ip_compute_csum(icmp, sizeof(struct icmphdr) + packet_len);              skb_push(skb, sizeof(struct ethhdr));       skb_reset_mac_header(skb);              struct ethhdr *eth_out = eth_hdr(skb);       memset(eth_out, 0, sizeof(struct ethhdr));       memcpy(eth_out-&gt;h_source, skb-&gt;dev-&gt;dev_addr, ETH_ALEN);       memcpy(eth_out-&gt;h_dest, mac_out, ETH_ALEN);       eth_out-&gt;h_proto = htons(0x0800);       skb_current = skb;       data_in += packet_len;       if (data_len == 0)           break;   }   skb_current = skb_out;      return skb_out;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<h4>\u0428\u0430\u0433 6.3 \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0440\u0438\u0451\u043c\u0430 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432<\/h4>\n<pre><code class=\"cpp\">struct list_data {    uint32_t size;    uint8_t* data;    void* prev;    void* next;};static int flag_error = 0;static int id_packet = 0;static int current_frag = 0;static struct list_data* end = NULL;static int total_size = 0;uint16_t id = ntohs(icmph-&gt;un.echo.id);struct transfer_header* header = (struct transfer_header*)&amp;id;if (ntohs(icmph-&gt;un.echo.sequence) == 0){    id_packet = header-&gt;id;    flag_error = 0;    clear_list (&amp;end);    current_frag = ntohs(icmph-&gt;un.echo.sequence);    total_size = 0;}if (flag_error == 1){    return NF_STOLEN;}if (current_frag == ntohs(icmph-&gt;un.echo.sequence)    &amp;&amp; id_packet == header-&gt;id){    current_frag++;    if (end)    {        end-&gt;next = kmalloc(sizeof(struct list_data), GFP_ATOMIC);        if (!end-&gt;next)        {            flag_error = 1;            return NF_STOLEN;        }        struct list_data* cur = end;        end = end-&gt;next;        end-&gt;prev = cur;            }    else    {        end = kmalloc(sizeof(struct list_data), GFP_ATOMIC);        if (!end)        {            flag_error = 1;            return NF_STOLEN;        }        end-&gt;prev = NULL;        end-&gt;next = NULL;    }    end-&gt;size = (uint8_t*)skb_tail_pointer(skb) - (uint8_t*)icmph - sizeof(struct icmphdr);    end-&gt;data = kmalloc(end-&gt;size, GFP_ATOMIC);    if (!end-&gt;data)    {        flag_error = 1;        return NF_STOLEN;    }    memcpy(end-&gt;data, (uint8_t*)(icmph + 1), end-&gt;size);    total_size += end-&gt;size;}else{    flag_error = 1;    clear_list (&amp;end);}if (header-&gt;last == 1 &amp;&amp; flag_error == 0){    pr_info (\"get packet %d %d\\n\",header-&gt;type, total_size);    struct sk_buff* skb_out = create_packet_input (skb, end, total_size);    if (!skb_out)    {        flag_error = 1;        clear_list (&amp;end);        pr_info (\"clear_list %u\\n\",end);        return NF_STOLEN;    }    struct task_data *data = kmalloc(sizeof(struct task_data), GFP_ATOMIC);    if (!data)    {        pr_err(\"kmalloc\\n\");        kfree_skb(skb_out);        return NF_ACCEPT;    }    data-&gt;skb = skb_out;    tasklet_init(&amp;data-&gt;tasklet, send_func, (unsigned long)data);    tasklet_schedule(&amp;data-&gt;tasklet);    }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p><code>if (ntohs(icmph-&gt;un.echo.sequence) == 0)<\/code> &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043d\u0430 \u043f\u0440\u0438\u0437\u043d\u0430\u043a \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u043f\u0430\u043a\u0435\u0442\u0435.<\/p>\n<\/li>\n<li>\n<p><code>if (current_frag == ntohs(icmph-&gt;un.echo.sequence) &amp;&amp; id_packet == header-&gt;id)<\/code> &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u0451\u043b \u0442\u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438.<\/p>\n<\/li>\n<li>\n<p><code>end-&gt;next = kmalloc(sizeof(struct list_data), GFP_ATOMIC);<\/code> \/ <code>end = kmalloc(sizeof(struct list_data), GFP_ATOMIC);<\/code> &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a.<\/p>\n<\/li>\n<li>\n<p><code>end-&gt;data = kmalloc(end-&gt;size, GFP_ATOMIC);<\/code> \/ <code>memcpy(end-&gt;data, (uint8_t*)(icmph + 1), end-&gt;size);<\/code> &#8212; \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><code>if (header-&gt;last == 1 &amp;&amp; flag_error == 0)<\/code> &#8212; \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0432\u0435\u0441\u044c \u043f\u0430\u043a\u0435\u0442, \u0442\u043e \u0441\u043a\u043b\u0435\u0438\u0432\u0430\u0435\u043c \u0435\u0433\u043e.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 6.4 \u0421\u043a\u043b\u0435\u0438\u0432\u0430\u0435\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0432 \u0435\u0434\u0438\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442<\/h4>\n<pre><code class=\"cpp\">if (header-&gt;type == 0) {    addr_transport_header = (uint8_t*)udp_hdr(skb); } else {      addr_transport_header = (uint8_t*)tcp_hdr(skb);}struct list_data* cur = end;int cp_size = total_size;while (cur){    cp_size -= cur-&gt;size;    memcpy (addr_transport_header + cp_size, cur-&gt;data, cur-&gt;size);    cur = cur-&gt;prev;}if (header-&gt;type == 0) {    transport_header_len = sizeof(struct udphdr);    struct udphdr* udph = udp_hdr(skb);    udph-&gt;check = 0;    } else {      struct tcphdr* tcph = tcp_hdr(skb);    struct tcphdr* tcp_in = (struct tcphdr*)data_in;    transport_header_len = __tcp_hdrlen(tcp_in);    tcph-&gt;check = 0;                tcph-&gt;check = tcp_v4_check(size,                                 ip_out-&gt;saddr,                                 ip_out-&gt;daddr,                                 csum_partial((char *)tcph, size, 0));    skb-&gt;ip_summed = CHECKSUM_NONE;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p><code>addr_transport_header = (uint8_t*)udp_hdr(skb);<\/code> \/ <code>addr_transport_header = (uint8_t*)tcp_hdr(skb);<\/code>  &#8212; \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0430\u0434\u0440\u0435\u0441 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.<\/p>\n<\/li>\n<li>\n<p><code>memcpy (addr_transport_header + cp_size, cur-&gt;data, cur-&gt;size);<\/code> &#8212; \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0444\u0440\u0435\u0439\u043c\u044b \u0441 \u043a\u043e\u043d\u0446\u0430 \u0432 \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u043a\u0435\u0442.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 6.5 \u0421\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c<\/h4>\n<ol>\n<li>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u0442\u0435 \u0436\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0447\u0442\u043e \u0438 \u0432 \u0448\u0430\u0433\u0435 5.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0431\u0435\u0436\u0434\u0430\u0435\u043c\u0441\u044f, \u0447\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f: <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7cf\/5fc\/9fd\/7cf5fc9fdeb06833ce4d9a38285b1051.JPG\" alt=\"messeger1\" width=\"1450\" height=\"600\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/7cf\/5fc\/9fd\/7cf5fc9fdeb06833ce4d9a38285b1051.JPG 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7cf\/5fc\/9fd\/7cf5fc9fdeb06833ce4d9a38285b1051.JPG 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>messeger1<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b captureEnp.pcap \u0438 \u0432\u0438\u0434\u0438\u043c \u0442\u0430\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0449\u0438\u0445 ICMP-\u043f\u0430\u043a\u0435\u0442\u043e\u0432: <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/692\/9de\/76e\/6929de76ee0aa859eda3b2cbaaaf767f.JPG\" alt=\"icmp2\" title=\"ICMP-\u043f\u0430\u043a\u0435\u0442\u044b\" width=\"2024\" height=\"949\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/692\/9de\/76e\/6929de76ee0aa859eda3b2cbaaaf767f.JPG 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/692\/9de\/76e\/6929de76ee0aa859eda3b2cbaaaf767f.JPG 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>ICMP-\u043f\u0430\u043a\u0435\u0442\u044b<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0444\u0430\u0439\u043b captureLo.pcap \u0438 \u0432\u0438\u0434\u0438\u043c \u0443\u0436\u0435 UDP, \u043d\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435: <\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/adf\/7a2\/bf1\/adf7a2bf1e38211f12d2cc86e8057b9b.JPG\" alt=\"udp2\" title=\"UDP-\u043f\u0430\u043a\u0442\u044b\" width=\"2094\" height=\"1090\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/adf\/7a2\/bf1\/adf7a2bf1e38211f12d2cc86e8057b9b.JPG 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/adf\/7a2\/bf1\/adf7a2bf1e38211f12d2cc86e8057b9b.JPG 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>UDP-\u043f\u0430\u043a\u0442\u044b<\/figcaption><\/div>\n<\/figure>\n<\/li>\n<\/ol>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 GitHub (<a href=\"https:\/\/github.com\/kormilicinkostia\/icmptunel\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/kormilicinkostia\/icmptunel<\/a>).<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c. \u041d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430 Linux \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0435\u043c \u043e\u0442\u0432\u0435\u0442\u043e\u0432. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0435\u0445\u0438 \u0438 \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u0445:<\/p>\n<ol>\n<li>\n<p>\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441\u043a\u043b\u0435\u0439\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u0415\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0438\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c, \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0430\u043a\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 user space, \u0430 \u043d\u0435 \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 lo-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0430 \u0441 \u044f\u0434\u0440\u043e\u043c Linux \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u044f \u0434\u043e\u0432\u043e\u043b\u0435\u043d.<\/p>\n<h3>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h3>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/ruvds\/articles\/681880\/\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0441\u043e\u0431\u0438\u0435 \u043f\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u044f\u0434\u0440\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/886058\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0443\u0442\u044c \u043f\u0430\u043a\u0435\u0442\u0430 \u0432 \u044f\u0434\u0440\u0435 Linux<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.opennet.ru\/base\/dev\/netfilter_lkm.txt.html\" rel=\"noopener noreferrer nofollow\">Netfilter-\u0445\u0443\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1025264\/\">https:\/\/habr.com\/ru\/articles\/1025264\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u044f \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044e \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 ICMP-\u043f\u0430\u043a\u0435\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0421\u0440\u0430\u0437\u0443 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043c\u044b\u0441\u043b\u044c: \u0430 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0433\u043d\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0442\u0440\u0430\u0444\u0438\u043a \u0447\u0435\u0440\u0435\u0437 ICMP (\u0434\u0430, \u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0438 ICMP-\u0442\u0443\u043d\u043d\u0435\u043b\u044f \u044f \u0442\u043e\u0436\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u043b). \u0422\u0430\u043a \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442 \u2014 ICMP-\u0442\u0443\u043d\u043d\u0435\u043b\u044c \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u044f\u0434\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439:\u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 TCP\/UDP-\u043f\u0430\u043a\u0435\u0442\u044b;\u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u0438\u0445 \u0432 ICMP \u044d\u0445\u043e-\u0437\u0430\u043f\u0440\u043e\u0441\u044b (\u0442\u0438\u043f ICMP_ECHO);\u043d\u0430 \u043f\u0440\u0438\u0451\u043c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0438\u0445 \u0434\u0430\u043b\u044c\u0448\u0435.\u0426\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u2014 \u0443\u0433\u043b\u0443\u0431\u0438\u0442\u044c \u0437\u043d\u0430\u043d\u0438\u044f \u0432:\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u044f\u0434\u0440\u0430 (\u0440\u0430\u0431\u043e\u0442\u0430 \u0441 sk_buff, \u0445\u0443\u043a\u0438 Netfilter, \u0442\u0430\u0441\u043a\u043b\u0435\u0442\u044b). \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 Linux \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 user space;\u0441\u0435\u0442\u0435\u0432\u043e\u043c \u0441\u0442\u0435\u043a\u0435 (IPv4, Ethernet, ICMP, TCP, UDP) \u0438, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 Linux. \u0414\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0441\u0435\u0442\u0435\u0432\u044b\u043c\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u043b\u0430\u0441\u044c \u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438;\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430\u0445 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0430 \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u0430\u043a\u0435\u0442\u043e\u0432.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0425\u0443\u043a NF_INET_POST_ROUTING &#8212; \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043a\u0438\u043d\u0443\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e user space \u0438 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u043e \u0441\u0435\u0442\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u043c\u0430\u0448\u0438\u043d\u0443:\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442 TCP\/UDP-\u0442\u0440\u0430\u0444\u0438\u043a;\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 \u0432 ICMP. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u0430\u043a\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: \u041f\u0430\u043a\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0445\u0425\u0443\u043a NF_INET_LOCAL_IN &#8212; \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0448\u043b\u0438 \u0432\u0441\u0435 \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0432 user space:\u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 ICMP-\u043f\u0430\u043a\u0435\u0442\u044b;\u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 TCP\/UDP-\u043f\u0430\u043a\u0435\u0442;\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 loopback-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 (lo) \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439.\u0422\u0430\u0441\u043a\u043b\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.\u0428\u0430\u0433 1. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0445\u0443\u043a\u043e\u0432inputHook.hook = input_hook;inputHook.hooknum = NF_INET_LOCAL_IN;inputHook.pf = PF_INET;inputHook.priority = NF_IP_PRI_FIRST;nf_register_net_hook(&amp;init_net, &amp;inputHook);outputHook.hook = output_hook;outputHook.hooknum = NF_INET_POST_ROUTING;outputHook.pf = PF_INET;outputHook.priority = NF_IP_PRI_FIRST;nf_register_net_hook(&amp;init_net, &amp;outputHook);\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:NF_INET_POST_ROUTING \u2014 \u0445\u0443\u043a \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430;NF_INET_LOCAL_IN \u2014 \u0445\u0443\u043a \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430;\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442  NF_IP_PRI_FIRST \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u043c.\u0428\u0430\u0433 2. \u0417\u0430\u0434\u0430\u0447\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441struct task_data {    struct tasklet_struct tasklet;    struct sk_buff *skb;};void send_func (unsigned long d){    struct task_data *data = (struct task_data *)d;    if (dev_queue_xmit(data-&gt;skb) != 0)     {        pr_err(&#171;dev_queue_xmit failed\\n&#187;);        kfree_skb(data-&gt;skb);    }    kfree (data);}\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0442\u0430\u0441\u043a\u043b\u0435\u0442\u044b. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043d\u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 (https:\/\/habr.com\/ru\/companies\/embox\/articles\/244071\/).sk_buff &#8212; \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u0435\u0442\u0435\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0432 \u044f\u0434\u0440\u0435 Linux.dev_queue_xmit &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0442\u0430\u0432\u0438\u0442 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0431\u0443\u0444\u0435\u0440 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e.\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0443\u0434\u0430\u0447\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0443\u0444\u0435\u0440\u0430 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0430\u0435\u043c sk_buff \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0430  kfree_skb(data-&gt;skb);\u041e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c, \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0434 \u0437\u0430\u0434\u0430\u0447\u0443 kfree (data)\u0428\u0430\u0433 3. \u0425\u0443\u043a NF_INET_POST_ROUTINGstatic unsigned int output_hook (void *priv, struct sk_buff *skb, const struct nf_hook_state *state){    struct sk_buff *skb_out = create_packet_output (skb);    if (!skb_out)        return NF_ACCEPT;        struct task_data *data = kmalloc (sizeof(struct task_data), GFP_ATOMIC);    if (!data)    {        pr_err(&#171;kmalloc\\n&#187;);        kfree_skb(skb_out);        return NF_ACCEPT;    }    data-&gt;skb = skb_out;    tasklet_init (&amp;data-&gt;tasklet, send_func, (unsigned long)data);    tasklet_schedule (&amp;data-&gt;tasklet);    return NF_STOLEN;}\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:\u0424\u0443\u043d\u043a\u0446\u0438\u044f create_packet_output; \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442 TCP\/UDP \u043f\u0430\u043a\u0435\u0442\u044b;\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 TCP\/UDP \u043f\u0430\u043a\u0435\u0442 \u0432 ICMP;\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 sk_buff \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.\u0415\u0441\u043b\u0438 \u043f\u0430\u043a\u0435\u0442 \u043d\u0435 \u043f\u0440\u043e\u0448\u0451\u043b \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u0438\u043b\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c  sk_buff , \u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0430\u043a\u0435\u0442 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 NF_ACCEPT;\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0442\u0430\u0441\u043a\u043b\u0435\u0442\u0430.\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443: tasklet_schedule (&amp;data-&gt;tasklet);NF_STOLEN &#8212; \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u044f\u0434\u0440\u0443, \u0447\u0442\u043e \u043f\u0430\u043a\u0435\u0442 \u043c\u044b \u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0430\u0434\u043e. \u0412\u0430\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e, \u0430 \u043d\u0435 NF_DROP.\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 create_packet_outputstatic struct sk_buff* create_packet_output(struct sk_buff* in_packet){       struct iphdr* ip_in = ip_hdr(in_packet);   uint8_t mac_out[ETH_ALEN];   uint8_t protocol_type;   uint16_t header_len;   void* transport_hdr;   uint16_t data_len;      if (ip_in-&gt;protocol != IPPROTO_UDP &amp;&amp; ip_in-&gt;protocol != IPPROTO_TCP)    {       return NULL;   }      if (find_mac_addr(mac_out, ip_in-&gt;daddr, in_packet-&gt;dev) &lt; 0)    {       pr_info(&#171;Not found mac\\n&#187;);       return NULL;   }      if (skb_linearize(in_packet))    {       pr_info(&#171;Failed to linearize skb\\n&#187;);       return NULL;   }      if (ip_in-&gt;protocol == IPPROTO_UDP)    {       struct udphdr* in_udp = udp_hdr(in_packet);       protocol_type = 0;         header_len = sizeof(struct udphdr);       transport_hdr = in_udp;       data_len = ntohs(in_udp-&gt;len) &#8212; sizeof(struct udphdr);   }    else    {        struct tcphdr* in_tcp = tcp_hdr(in_packet);       protocol_type = 1;         header_len = tcp_hdrlen(in_packet);       transport_hdr = in_tcp;       data_len = ntohs(ip_in-&gt;tot_len) &#8212; (ip_in-&gt;ihl * 4) &#8212; header_len;   }      int packet_size = sizeof(struct ethhdr)                    + sizeof(struct iphdr)                    + sizeof(struct icmphdr)                   + header_len                   + data_len;      int hh_len = LL_RESERVED_SPACE(in_packet-&gt;dev);   int tlen = in_packet-&gt;dev-&gt;needed_tailroom;   struct sk_buff* skb = netdev_alloc_skb(in_packet-&gt;dev, hh_len + tlen + packet_size);   if (unlikely(!skb))    {       pr_err(&#171;netdev_alloc_skb failed\\n&#187;);       return NULL;   }      skb_reserve(skb, hh_len);   skb-&gt;dev = in_packet-&gt;dev;   skb-&gt;protocol = htons(ETH_P_IP);   skb_put(skb, packet_size);   skb_reset_network_header(skb);   skb_set_transport_header(skb, sizeof(struct iphdr));      struct iphdr* ip_out = ip_hdr(skb);   ip_out-&gt;version = 4;   ip_out-&gt;ihl = 5;   ip_out-&gt;tos = 0;   ip_out-&gt;tot_len = htons(packet_size &#8212; sizeof(struct ethhdr));   ip_out-&gt;id = 0;   ip_out-&gt;frag_off = htons(0x4000);   ip_out-&gt;ttl = 64;   ip_out-&gt;protocol = IPPROTO_ICMP;   ip_out-&gt;saddr = ip_in-&gt;saddr;   ip_out-&gt;daddr = ip_in-&gt;daddr;   ip_out-&gt;check = 0;   ip_out-&gt;check = ip_fast_csum((u8 *)ip_out, ip_out-&gt;ihl);      struct transfer_header header;   static uint8_t id = 0;   header.id = id++;   header.last = 1;   header.type = protocol_type;      struct icmphdr* icmp = icmp_hdr(skb);   icmp-&gt;type = ICMP_ECHO;   icmp-&gt;code = 0;   icmp-&gt;checksum = 0;   icmp-&gt;un.echo.id = htons(*(uint16_t*)&amp;header);   icmp-&gt;un.echo.sequence = 1;      uint8_t* data_out = (uint8_t*)(icmp + 1);   memcpy(data_out, transport_hdr, header_len);   data_out += header_len;      uint8_t* data_in = (uint8_t*)transport_hdr + header_len;   memcpy(data_out, data_in, data_len);      icmp-&gt;checksum = ip_compute_csum(icmp, sizeof(struct icmphdr) + header_len + data_len);      skb_push(skb, sizeof(struct ethhdr));   skb_reset_mac_header(skb);      struct ethhdr *eth_out = eth_hdr(skb);   memset(eth_out, 0, sizeof(struct ethhdr));   memcpy(eth_out-&gt;h_source, skb-&gt;dev-&gt;dev_addr, ETH_ALEN);   memcpy(eth_out-&gt;h_dest, mac_out, ETH_ALEN);   eth_out-&gt;h_proto = htons(0x0800);      return skb;}\u0428\u0430\u0433 3.1. \u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f TCP\/UDP \u043f\u0430\u043a\u0435\u0442\u044bstruct iphdr* ip_in = ip_hdr(in_packet);if (ip_in-&gt;protocol != IPPROTO_UDP &amp;&amp; ip_in-&gt;protocol != IPPROTO_TCP) {    return NULL;}\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:\u0410\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f. \u0414\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u0438 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f IPv4. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e ip_hdr;\u0417\u0430 \u0442\u0438\u043f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u0432 IPv4 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u0435 protocol. \u0414\u043b\u044f TCP \u043e\u043d\u043e \u0440\u0430\u0432\u043d\u043e 6, \u0434\u043b\u044f UDP \u2014 17, \u0434\u043b\u044f ICMP \u2014 1.\u0428\u0430\u0433 3.2. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435  sk_buffif (ip_in-&gt;protocol == IPPROTO_UDP) {    struct udphdr* in_udp = udp_hdr(in_packet);    protocol_type = 0;      header_len = sizeof(struct udphdr);    transport_hdr = in_udp;    data_len = ntohs(in_udp-&gt;len) &#8212; sizeof(struct udphdr);} else {     struct tcphdr* in_tcp = tcp_hdr(in_packet);    protocol_type = 1;      header_len = tcp_hdrlen(in_packet);    transport_hdr = in_tcp;    data_len = ntohs(ip_in-&gt;tot_len) &#8212; (ip_in-&gt;ihl * 4) &#8212; header_len;}int packet_size = sizeof(struct ethhdr)                     + sizeof(struct iphdr)                     + sizeof(struct icmphdr)                    + header_len                    + data_len;    int hh_len = LL_RESERVED_SPACE(in_packet-&gt;dev);int tlen = in_packet-&gt;dev-&gt;needed_tailroom;struct sk_buff* skb = netdev_alloc_skb(in_packet-&gt;dev, hh_len + tlen + packet_size);\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430: header_len = sizeof(struct udphdr); \/  header_len = tcp_hdrlen(in_packet);;\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:  data_len = ntohs(in_udp-&gt;len) &#8212; sizeof(struct udphdr); \/data_len = ntohs(ip_in-&gt;tot_len) &#8212; (ip_in-&gt;ihl * 4) &#8212; header_len; ;\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: sizeof(struct ethhdr) ;\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: sizeof(struct iphdr);\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f:sizeof(struct icmphdr);\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0441\u0442\u043e \u043f\u043e\u0434 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435: header_len + data_len;\u0420\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u0443\u0435\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u043f\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 LL_RESERVED_SPACE(in_packet-&gt;dev), in_packet-&gt;dev-&gt;needed_tailroom\u0428\u0430\u0433 3.3. \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043a\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044fstatic int find_mac_addr (uint8_t* mac, uint32_t ip, struct net_device *dev){    struct neighbour *neigh = __ipv4_neigh_lookup(dev, ip);    if (neigh &amp;&amp; (neigh-&gt;nud_state &amp; NUD_VALID))     {        memcpy(mac, neigh-&gt;ha, ETH_ALEN);        neigh_release(neigh);        return 0;    }    return -1;}skb_push(skb, sizeof(struct ethhdr));skb_reset_mac_header(skb);struct ethhdr *eth_out = eth_hdr(skb);memset(eth_out, 0, sizeof(struct ethhdr));memcpy(eth_out-&gt;h_source, skb-&gt;dev-&gt;dev_addr, ETH_ALEN);memcpy(eth_out-&gt;h_dest, mac_out, ETH_ALEN);eth_out-&gt;h_proto = htons(0x0800);\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u0430\u043a\u0435\u0442\u0430 \u0438\u0437 user space \u0443 \u043d\u0430\u0441 \u0435\u0449\u0451 \u043d\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-476555","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/476555","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=476555"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/476555\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=476555"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=476555"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=476555"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}