изменение заголовка ip в модуле ядра разрывает соединение

У меня есть модуль ядра, в котором:

  • Он изменяет поле saddr исходящих пакетов и исправляет его обратно (daddr) в входящих пакетах ...
  • Я вычисляю новую контрольную сумму для заголовков ip и tcp ...

Итак, на стороне клиента я меняю ip - сторона сервера получает его (пакет SYN) и отправляет пакет (SYN-ACK), но сторона клиента - отправляет (сброс) пакеты и пытается снова обработать рукопожатие tcp ...

Я видел другие примеры модулей ядра - dnat / snat - мой код аналогичен? Из-за моего be ebtables мои хуки работают некорректно?

Интерфейсы: eth0 - XXX.XXX.XXX.1 eth0: 0 (псевдоним) - XXX.XXX.XXX.2

 /*
 Client (original ip XX.XX.XX.1)                                                                                                                         SERVER (ip YY.YY.YY.YY)
 USER-SPACE app creates tcp-socket and connects to (YY.YY.YY.YY)

  1) 
 TCP (SYN) -----------(packet ip XX.XX.XX.1-YY.YY.YY.YY[ip.sum1, tcp.sum1] )----->
 NF_INET_POST_ROUTING ( ip XX.XX.XX.2-YY.YY.YY.YY[ip.sum2, tcp.sum2] )
 =============================================================================>
 2)
 <-------TCP (SYN ACK) ------(packet ip YY.YY.YY.YY-XX.XX.XX.2[ip.sum1, tcp.sum1])
 NF_INET_PRE_ROUTING ( ip YY.YY.YY.YY-XX.XX.XX.1[ip.sum2, tcp.sum2] )
<==============================================================================


 3)

 TCP (RST) - against TCP (ACK) - that is the question ....
 =============================================================================>

  */

/ * vars.c * /

 struct in_addr orig_addr;
 struct in_addr virt_addr;
 pid_t pid_to_handle;


 void init_vars()
 {
      pid_to_handle = 0xAAAA;
      inet_pton(AF_INET, "XX.XX.XX.1", &orig_addr);
      inet_pton(AF_INET, "XX.XX.XX.2", &virt_addr);
 }

/ * init.c * /

 void register_handlers()
 {
      ...

      int ret;
      hook_out.hooknum  = NF_INET_POST_ROUTING;
      hook_out.hook     = process_out;
      hook_out.pf       = PF_INET;
      hook_out.owner    = THIS_MODULE;
      hook_out.priority = NF_IP_PRI_LAST;
      ret = nf_register_hook(&hook_out);

      hook_in.hooknum  = NF_INET_PRE_ROUTING;
      hook_in.hook     = process_in;
      hook_in.pf       = PF_INET;
      hook_in.owner    = THIS_MODULE;
      hook_in.priority = NF_IP_PRI_FIRST;
      ret = nf_register_hook(&hook_in);
      ....

  }

/ * out.c * /

 unsigned int process_out(
           unsigned int hooknum,
           struct sk_buff *skb,
           const struct net_device *in,
           const struct net_device *out,
           int (*okfn)(struct sk_buff *))
 {
      int i;
      struct iphdr *iph;
      struct tcphdr *tcp_header;
      ....

      {
           if ( skb->sk ) {
                if ( skb->sk ) {
                     struct socket * s = skb->sk->sk_socket;
                     if ( s ) {
                          struct file *f = s->file;

                          if ( f ) {
                               struct task_struct *task;
                               struct files_struct *files;

                               for_each_process(task) {
                                    if ( task->pid == pid_to_handle ) {
                                         task_lock(task);
                                         files = task->files;

                                         if ( files ) {
                                              read_lock(&files->file_lock);

                                              for ( i=0; i<1024; i++ ) {
                                                   if ( fcheck_files(files, i) == f ) {
                                                        iph->saddr = virt_addr.s_addr;
                                                        iph->check = 0;
                                                        ip_send_check (iph);

                                                        tcp_header->check = 0;
                                                        tcp_header->check = get_packet_checksum(
                                                                  iph, tcp_header, pseudogram_out, datagram_out);

                                                   }
                                              }

                                              read_unlock(&files->file_lock);
                                         }

                                         task_unlock(task);
                                    }
                               }
                          }

                     }
                }
           }
      }

      return NF_ACCEPT;
 }

/* in.c */

 unsigned int process_in(
           unsigned int hooknum,
           struct sk_buff *skb,
           const struct net_device *in,
           const struct net_device *out,
           int (*okfn)(struct sk_buff *))
 {
      struct iphdr *iph;
      struct tcphdr *tcp_header;
      ...

      {
           if ( iphdr->daddr == virt_addr.s_addr ) {
                iphdr->daddr = orig_addr.s_addr;

                iph->check = 0;
                iph->check = ip_fast_csum(iph, iph->ihl);

                tcp_header->check = 0;
                tcp_header->check = get_packet_checksum(
                          iph, tcp_header, pseudogram_in, datagram_in);
           }
      }

      return NF_ACCEPT;
 }

/ * utils.c * /

 struct pseudo_header
 {
      u_int32_t source_address;
      u_int32_t dest_address;
      u_int8_t placeholder;
      u_int8_t protocol;
      u_int16_t tcp_length;
 };

 /*
      Generic checksum calculation function
 */
 unsigned short csum(unsigned short *ptr,int nbytes) {
      register long sum;
      unsigned short oddbyte;
      register short answer;

      sum = 0;
      while (nbytes > 1) {
           sum += *ptr++;
           nbytes -= 2;
      }
      if (nbytes == 1) {
           oddbyte = 0;
           *((u_char * ) & oddbyte) = *(u_char *) ptr;
           sum += oddbyte;
      }

      sum = (sum >> 16) + (sum & 0xffff);
      sum = sum + (sum >> 16);
      answer = (short) ~sum;

      return (answer);

 }

 static char *pseudogram_out = NULL;
 static char *datagram_out = NULL;
 static char *pseudogram_in = NULL;
 static char *datagram_in = NULL;


 int get_packet_checksum(struct iphdr *ip_header, struct tcphdr *tcp_header, char *pseudogram, char *datagram)
 {
      if ( (pseudogram == NULL) || (datagram == NULL) )
           return -1;

      char source_ip[32] , *data;
      memset (datagram, 0, 4096);
      memset (pseudogram, 0, 4096);
      memcpy(datagram, ip_header, ip_header->tot_len);
      ip_header = (struct iphdr *)datagram;
      tcp_header = (struct tcphdr *)(datagram + sizeof(struct iphdr));

      struct sockaddr_in sin;
      struct pseudo_header psh;
      size_t tcp_data_len = ip_header->tot_len - sizeof(struct iphdr) - sizeof(struct tcphdr);

      psh.source_address = ip_header->saddr;
      psh.dest_address = ip_header->daddr;
      psh.placeholder = 0;
      psh.protocol = IPPROTO_TCP;
      psh.tcp_length = htons(sizeof(struct tcphdr) + tcp_data_len );

      int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + tcp_data_len;
      memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
      memcpy(pseudogram + sizeof(struct pseudo_header) , tcp_header , sizeof(struct tcphdr) + tcp_data_len);

      return csum((unsigned short*)pseudogram, psize);
 }

Журнал tcpump на сервере:

11:27:03.164239 IP (tos 0x0, ttl 48, id 61125, offset 0, flags [DF], proto TCP (6), length 60)
    XXX.XXX.XXX.x2.33782 > YYY.YY.YYY.YYY.8999: Flags [S], cksum 0xa1cb (correct), seq 492452010, win 5840, options [mss 1448,sackOK,TS val 251503 ecr 0,nop,wscale 1], length 0
    0x0000:  4500 003c eec5 4000 3006 a014 xxxx xxx2  E..<[email protected]}.
    0x0010:  yyyy yyyy 83f6 2327 1d5a 38aa 0000 0000  .E....#'.Z8.....
    0x0020:  a002 16d0 a1cb 0000 0204 05a8 0402 080a  ................
    0x0030:  0003 d66f 0000 0000 0103 0301            ...o........
11:27:03.164394 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    YYY.YY.YYY.YYY.8999 > XXX.XXX.XXX.x2.33782: Flags [S.], cksum 0xbc10 (incorrect -> 0x597a), seq 1446351294, ack 492452011, win 28960, options [mss 1460,sackOK,TS val 842060729 ecr 251503,nop,wscale 7], length 0
    0x0000:  4500 003c 0000 4000 4006 7eda yyyy yyyy  E..<..@.@.~..E..
    0x0010:  xxxx xxx2 2327 83f6 5635 91be 1d5a 38ab  .5}.#'..V5...Z8.
    0x0020:  a012 7120 bc10 0000 0204 05b4 0402 080a  ..q.............
    0x0030:  3230 d3b9 0003 d66f 0103 0307            20.....o....
11:27:04.181972 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    YYY.YY.YYY.YYY.8999 > XXX.XXX.XXX.x2.33782: Flags [S.], cksum 0xbc10 (incorrect -> 0x587b), seq 1446351294, ack 492452011, win 28960, options [mss 1460,sackOK,TS val 842060984 ecr 251503,nop,wscale 7], length 0
    0x0000:  4500 003c 0000 4000 4006 7eda yyyy yyyy  E..<..@.@.~..E..
    0x0010:  xxxx xxx2 2327 83f6 5635 91be 1d5a 38ab  .5}.#'..V5...Z8.
    0x0020:  a012 7120 bc10 0000 0204 05b4 0402 080a  ..q.............
    0x0030:  3230 d4b8 0003 d66f 0103 0307            20.....o....
11:27:05.525221 IP (tos 0x0, ttl 48, id 61126, offset 0, flags [DF], proto TCP (6), length 60)
    XXX.XXX.XXX.x2.33782 > YYY.YY.YYY.YYY.8999: Flags [S], cksum 0x9612 (correct), seq 492452010, win 5840, options [mss 1448,sackOK,TS val 254504 ecr 0,nop,wscale 1], length 0
    0x0000:  4500 003c eec6 4000 3006 a013 xxxx xxx2  E..<[email protected]}.
    0x0010:  yyyy yyyy 83f6 2327 1d5a 38aa 0000 0000  .E....#'.Z8.....
    0x0020:  a002 16d0 9612 0000 0204 05a8 0402 080a  ................
    0x0030:  0003 e228 0000 0000 0103 0301            ...(........
11:27:05.525319 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    YYY.YY.YYY.YYY.8999 > XXX.XXX.XXX.x2.33782: Flags [S.], cksum 0xbc10 (incorrect -> 0x572c), seq 1446351294, ack 492452011, win 28960, options [mss 1460,sackOK,TS val 842061319 ecr 251503,nop,wscale 7], length 0
    0x0000:  4500 003c 0000 4000 4006 7eda yyyy yyyy  E..<..@.@.~..E..
    0x0010:  xxxx xxx2 2327 83f6 5635 91be 1d5a 38ab  .5}.#'..V5...Z8.
    0x0020:  a012 7120 bc10 0000 0204 05b4 0402 080a  ..q.............
    0x0030:  3230 d607 0003 d66f 0103 0307            20.....o....
11:27:07.541981 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    YYY.YY.YYY.YYY.8999 > XXX.XXX.XXX.x2.33782: Flags [S.], cksum 0xbc10 (incorrect -> 0x5533), seq 1446351294, ack 492452011, win 28960, options [mss 1460,sackOK,TS val 842061824 ecr 251503,nop,wscale 7], length 0
    0x0000:  4500 003c 0000 4000 4006 7eda yyyy yyyy  E..<..@.@.~..E..
    0x0010:  xxxx xxx2 2327 83f6 5635 91be 1d5a 38ab  .5}.#'..V5...Z8.
    0x0020:  a012 7120 bc10 0000 0204 05b4 0402 080a  ..q.............
    0x0030:  3230 d800 0003 d66f 0103 0307            20.....o....
11:27:11.524252 IP (tos 0x0, ttl 48, id 61127, offset 0, flags [DF], proto TCP (6), length 60)
    XXX.XXX.XXX.x2.33782 > YYY.YY.YYY.YYY.8999: Flags [S], cksum 0x7ea2 (correct), seq 492452010, win 5840, options [mss 1448,sackOK,TS val 260504 ecr 0,nop,wscale 1], length 0
    0x0000:  4500 003c eec7 4000 3006 a012 xxxx xxx2  E..<[email protected]}.
    0x0010:  yyyy yyyy 83f6 2327 1d5a 38aa 0000 0000  .E....#'.Z8.....
    0x0020:  a002 16d0 7ea2 0000 0204 05a8 0402 080a  ....~...........
    0x0030:  0003 f998 0000 0000 0103 0301            ............
11:27:11.524331 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    YYY.YY.YYY.YYY.8999 > XXX.XXX.XXX.x2.33782: Flags [S.], cksum 0xbc10 (incorrect -> 0x5150), seq 1446351294, ack 492452011, win 28960, options [mss 1460,sackOK,TS val 842062819 ecr 251503,nop,wscale 7], length 0
    0x0000:  4500 003c 0000 4000 4006 7eda yyyy yyyy  E..<..@.@.~..E..
    0x0010:  xxxx xxx2 2327 83f6 5635 91be 1d5a 38ab  .5}.#'..V5...Z8.
    0x0020:  a012 7120 bc10 0000 0204 05b4 0402 080a  ..q.............
    0x0030:  3230 dbe3 0003 d66f 0103 0307            20.....o....

tcpdump на клиенте:

     06:27:02.370828 IP (tos 0x0, ttl 64, id 61125, offset 0, flags [DF], proto TCP (6), length 60) xxx.xxx.xxx.X2.33782 > YYY.YY.YYY.YYY.8999: S, cksum 0xa1bf (correct), 492452010:492452010(0) win 5840 <mss 1460,sackOK,timestamp 251503 0,nop,wscale 1>
      0x0000:  4500 003c eec5 4000 4006 9014 xxxx xxx2  E..<..@[email protected]}.
      0x0010:  yyyy yyyy 83f6 2327 1d5a 38aa 0000 0000  .E....#'.Z8.....
      0x0020:  a002 16d0 a1bf 0000 0204 05b4 0402 080a  ................
      0x0030:  0003 d66f 0000 0000 0103 0301            ...o........
 06:27:03.301644 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x5986 (correct), 1446351294:1446351294(0) ack 492452011 win 28960 <mss 1448,sackOK,timestamp 842060729 251503,nop,wscale 7>
      0x0000:  4500 003c 0000 4000 3506 89d9 yyyy yyyy  E..<[email protected]..
      0x0010:  xxxx xxx1 2327 83f6 5635 91be 1d5a 38ab  .4}.#'..V5...Z8.
      0x0020:  a012 7120 5986 0000 0204 05a8 0402 080a  ..q.Y...........
      0x0030:  3230 d3b9 0003 d66f 0103 0307            20.....o....
 06:27:04.318359 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x5887 (correct), 1446351294:1446351294(0) ack 492452011 win 28960 <mss 1448,sackOK,timestamp 842060984 251503,nop,wscale 7>
      0x0000:  4500 003c 0000 4000 3506 89d9 yyyy yyyy  E..<[email protected]..
      0x0010:  xxxx xxx1 2327 83f6 5635 91be 1d5a 38ab  .4}.#'..V5...Z8.
      0x0020:  a012 7120 5887 0000 0204 05a8 0402 080a  ..q.X...........
      0x0030:  3230 d4b8 0003 d66f 0103 0307            20.....o....
 06:27:05.371079 IP (tos 0x0, ttl 64, id 61126, offset 0, flags [DF], proto TCP (6), length 60) xxx.xxx.xxx.X2.33782 > YYY.YY.YYY.YYY.8999: S, cksum 0x9606 (correct), 492452010:492452010(0) win 5840 <mss 1460,sackOK,timestamp 254504 0,nop,wscale 1>
      0x0000:  4500 003c eec6 4000 4006 9013 xxxx xxx2  E..<..@[email protected]}.
      0x0010:  yyyy yyyy 83f6 2327 1d5a 38aa 0000 0000  .E....#'.Z8.....
      0x0020:  a002 16d0 9606 0000 0204 05b4 0402 080a  ................
      0x0030:  0003 e228 0000 0000 0103 0301            ...(........
 06:27:05.661863 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x5738 (correct), 1446351294:1446351294(0) ack 492452011 win 28960 <mss 1448,sackOK,timestamp 842061319 251503,nop,wscale 7>
      0x0000:  4500 003c 0000 4000 3506 89d9 yyyy yyyy  E..<[email protected]..
      0x0010:  xxxx xxx1 2327 83f6 5635 91be 1d5a 38ab  .4}.#'..V5...Z8.
      0x0020:  a012 7120 5738 0000 0204 05a8 0402 080a  ..q.W8..........
      0x0030:  3230 d607 0003 d66f 0103 0307            20.....o....
 06:27:07.677895 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x553f (correct), 1446351294:1446351294(0) ack 492452011 win 28960 <mss 1448,sackOK,timestamp 842061824 251503,nop,wscale 7>
      0x0000:  4500 003c 0000 4000 3506 89d9 yyyy yyyy  E..<[email protected]..
      0x0010:  xxxx xxx1 2327 83f6 5635 91be 1d5a 38ab  .4}.#'..V5...Z8.
      0x0020:  a012 7120 553f 0000 0204 05a8 0402 080a  ..q.U?..........
      0x0030:  3230 d800 0003 d66f 0103 0307            20.....o....
 06:27:11.371065 IP (tos 0x0, ttl 64, id 61127, offset 0, flags [DF], proto TCP (6), length 60) xxx.xxx.xxx.X2.33782 > YYY.YY.YYY.YYY.8999: S, cksum 0x7e96 (correct), 492452010:492452010(0) win 5840 <mss 1460,sackOK,timestamp 260504 0,nop,wscale 1>
      0x0000:  4500 003c eec7 4000 4006 9012 xxxx xxx2  E..<..@[email protected]}.
      0x0010:  yyyy yyyy 83f6 2327 1d5a 38aa 0000 0000  .E....#'.Z8.....
      0x0020:  a002 16d0 7e96 0000 0204 05b4 0402 080a  ....~...........
      0x0030:  0003 f998 0000 0000 0103 0301            ............
 06:27:11.660592 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x515c (correct), 1446351294:1446351294(0) ack 492452011 win 28960 <mss 1448,sackOK,timestamp 842062819 251503,nop,wscale 7>
      0x0000:  4500 003c 0000 4000 3506 89d9 yyyy yyyy  E..<[email protected]..
      0x0010:  xxxx xxx1 2327 83f6 5635 91be 1d5a 38ab  .4}.#'..V5...Z8.
      0x0020:  a012 7120 515c 0000 0204 05a8 0402 080a  ..q.Q\..........
      0x0030:  3230 dbe3 0003 d66f 0103 0307            20.....o....
 06:27:15.870063 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x4d3f (correct), 1446351294:1446351294(0) ack 492452011 win 28960 <mss 1448,sackOK,timestamp 842063872 251503,nop,wscale 7>
      0x0000:  4500 003c 0000 4000 3506 89d9 yyyy yyyy  E..<[email protected]..
      0x0010:  xxxx xxx1 2327 83f6 5635 91be 1d5a 38ab  .4}.#'..V5...Z8.
      0x0020:  a012 7120 4d3f 0000 0204 05a8 0402 080a  ..q.M?..........
      0x0030:  3230 e000 0003 d66f 0103 0307            20.....o....
 06:27:24.062254 IP (tos 0x0, ttl 53, id 0, offset 0, flags [DF], proto TCP (6), length 60, bad cksum 89d9 (->89da)!) YYY.YY.YYY.YYY.8999 > xxx.xxx.xxx.x1.33782: S, cksum 0x453f (correct), 1446351294:1446351294(0) ack 492452011

person Andriy Vasyltsiv    schedule 17.01.2018    source источник
comment
Вы модифицируете стек IP или просто сами изменяете заголовки? Если вы возитесь с заголовками, конечно, настоящий IP-стек будет отправлять RST-пакеты обратно; он ничего не знает о пакетах.   -  person David Hoelzer    schedule 17.01.2018
comment
Я только заголовки модифицирую .... что мне нужно, чтобы IP стек не сбрасывал входящие пакеты ???   -  person Andriy Vasyltsiv    schedule 17.01.2018
comment
Используйте стек IP. Как вариант ... Отправлю ответ.   -  person David Hoelzer    schedule 17.01.2018
comment
AFAIK это должно работать нормально с правильными хуками netfilter. Можете ли вы использовать tcpdump / wirehark на клиентской машине, чтобы увидеть пакет, который он получает? Также опубликуйте свой код / ​​псевдокод.   -  person YSK    schedule 20.01.2018
comment
@YSK Я не могу вставить фрагменты кода, поэтому вот ссылки ...: фрагменты модуля ядра: [pastebin.com/hJQ91uje [ pastebin.com/C4gDukLD] XXX.XXX.XXX.1 - IP-адрес интерфейса eth0 XXX.XXX.XXX. 2 - eth0: 0 псевдоним IP YYY.YYY.YYY.YYY - IP сервера   -  person Andriy Vasyltsiv    schedule 22.01.2018
comment
Ссылки пустые ...   -  person YSK    schedule 22.01.2018
comment
@YSK - Извините. Я обновил предположение ....   -  person Andriy Vasyltsiv    schedule 22.01.2018


Ответы (1)


Судя по тому, что вы говорите, проблема в том, что вы изменяете аспекты пакета вне стека TCP / IP. Это создает ситуацию, когда возвращаемый SYN / ACK, например, не будет связан с каким-либо соединением, о котором знает стек TCP / IP, поэтому он отреагирует сбросом соединения.

Быстрый и грязный способ обойти это - использовать брандмауэр IPTables, чтобы система не могла отправлять исходящие пакеты RST. Конечно, это означает, что ваша обработка пакетов также не сможет отправлять исходящие пакеты RST.

iptables -I INPUT -p tcp --tcp-flags RST RST -j DROP

person David Hoelzer    schedule 17.01.2018
comment
возможно, я объяснил не полностью, в этом вопросе я использовал простую схему моей проблемы .... stackoverflow.com/questions/48302523/ - Я не создаю сырые пакеты, но модифицируя те, которые были созданы приложением пользовательского пространства .... и некоторая структура сокетов связана с ними в пространстве ядра .... - person Andriy Vasyltsiv; 17.01.2018
comment
Если вы измените их после того, как они покинут стек TCP / IP, стек не распознает возвращаемые ACK. - person David Hoelzer; 17.01.2018