【问题标题】:iptables in android安卓中的iptables
【发布时间】:2011-06-02 09:54:35
【问题描述】:

IPtables 是内置在 android 内核中的吗?如果是,如何在我们的 android 应用程序中使用它们?

【问题讨论】:

  • 你想做什么?我不会弄乱 iptables 设置(如果可以的话)。这听起来很恶意。
  • 我正在编写一个类似防火墙的小型应用程序来限制某些网站。现在,根据我得到的一个答案,我将不得不创建 iptables 二进制文件,我该怎么做(如何创建 iptables 二进制文件)。稍后我可能不得不使用它并编辑一些规则。
  • 嗨 Preetam!我也在尝试使用 iptables 创建防火墙!你能告诉我你是怎么做到的吗
  • 我是在 emulator2.1 上完成的,我交叉编译了 android 内核并启用了 netfilter 以使用 iptables。一旦你实现了这一点,你就可以将 iptables 规则集应用到你的内核。 android 使用精简版的 iptables github.com/android/platform_external_iptables。如果想要更多功能,可以交叉编译iptablesrandomizedsort.blogspot.in/2011/03/…。只要做一些研发,你就会得到它。

标签: android networking iptables


【解决方案1】:
  1. iptables 在 Android 源代码分发中可用。但该版本仅适用于使用 Linux 内核 2.6.29 构建的设备。
  2. 零售 Android 设备的用户无法访问 iptables 二进制文件。甚至 Android 操作系统本身也无法访问该二进制文件。这在 Android 中是硬编码的。许多设备也根本没有 iptables。
  3. 访问 iptables 二进制文件的唯一方法是构建您自己的 Android 映像。查看http://randomizedsort.blogspot.com/2010/08/building-android-and-linux-kernel-for.html。熟悉该过程后,请查看http://randomizedsort.blogspot.com/2011/03/porting-iptables-1410-to-android.html

【讨论】:

  • 非常非常感谢!实际上我已经编译了自己的 Android Image(zImage),但是在模拟器中加载它时出错。请检查此链接stackoverflow.com/questions/5406549/…
  • 这不再是真的,在我最近尝试过的每台 ICS+ 设备上都有 netfilter 支持,因此 iptables 二进制文件可以按原样安装和使用,给定设备显然是 root。
【解决方案2】:

This 是一个已有 5 年历史的解决方案(需要 root):

但随着 Google 代码变为只读状态,将继续正常工作直到“至少 2016 年 1 月”,这意味着下个月这个答案可能没用。

【讨论】:

    【解决方案3】:

    使用 root 手机,尝试使用 busybox 和终端运行“iptables -L”来列出当前表。我发现我所要做的就是将我的手机 root 并在我原本零售的 android 上安装 Iptables。一旦设备确认了 iptables,您就可以通过您的应用使用命令行来调整表格。

    【讨论】:

      【解决方案4】:

      iptables 是 AOSP 中的默认模块,您可以使用 netfilter 编写 c 代码来处理。

      比如你可以创建一个android项目,写一个JNI文件,使用ndk-build编译,然后adb push 可执行文件到android文件系统执行。而在移动端,你可以 adb shell 到它,直接以 root 用户使用 iptables 命令,就像在 linux 中一样。

      附件:

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <sys/socket.h>
      #include <netinet/in.h>
      #include <arpa/inet.h>
      #include <linux/types.h>
      #include <linux/ip.h>
      #include <linux/tcp.h>
      #include <linux/netfilter.h>        /* for NF_ACCEPT */
      #include <errno.h>
      
      #include <libnetfilter_queue/libnetfilter_queue.h>
      
      #ifdef __LITTLE_ENDIAN
      #define IPQUAD(addr) \
          ((unsigned char *)&addr)[0], \
          ((unsigned char *)&addr)[1], \
          ((unsigned char *)&addr)[2], \
          ((unsigned char *)&addr)[3]
      #else
      #define IPQUAD(addr) \
          ((unsigned char *)&addr)[3], \
          ((unsigned char *)&addr)[2], \
          ((unsigned char *)&addr)[1], \
          ((unsigned char *)&addr)[0]
      #endif
      
      
      #define TO "192.168.191.129"
      #define NAT_TO "192.168.2.246"
      
      struct tcp_pseudo /*the tcp pseudo header*/
      {
          __u32 src_addr;
          __u32 dst_addr;
          __u8 zero;
          __u8 proto;
          __u16 length;
      } pseudohead;
      
      
      long checksum(unsigned short *addr, unsigned int count) {
          /* Compute Internet Checksum for "count" bytes
         * beginning at location "addr".
         */
          register long sum = 0;
      
          while( count > 1 ) {
              /* This is the inner loop */
              sum += * addr++;
              count -= 2;
          }
          /* Add left-over byte, if any */
          if( count > 0 )
              sum += * (unsigned char *) addr;
      
          /* Fold 32-bit sum to 16 bits */
          while (sum>>16)
              sum = (sum & 0xffff) + (sum >> 16);
      
          return ~sum;
      }
      
      
      
      /*************************tcp checksum**********************/
      long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
      
          __u16 total_len = ntohs(myip->tot_len);
      
          int tcpopt_len = mytcp->doff*4 - 20;
          int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
      
          pseudohead.src_addr=myip->saddr;
          pseudohead.dst_addr=myip->daddr;
          pseudohead.zero=0;
          pseudohead.proto=IPPROTO_TCP;
          pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
      
          int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + tcpopt_len +tcpdatalen;
          //unsigned short * tcp = new unsigned short[totaltcp_len];
      
          unsigned short * tcp = malloc(totaltcp_len);
      
      
          memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
          memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned char*)mytcp,sizeof(struct tcphdr));
          memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr),(unsigned char *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
          memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char *)mytcp+(mytcp->doff*4), tcpdatalen);
      
          /* printf("pseud length: %d\n",pseudohead.length);
                printf("tcp hdr length: %d\n",mytcp->doff*4);
                printf("tcp hdr struct length: %d\n",sizeof(struct tcphdr));
                printf("tcp opt length: %d\n",tcpopt_len);
                printf("tcp total+psuedo length: %d\n",totaltcp_len);
      
                fflush(stdout);
      
                printf("tcp data len: %d, data start %u\n", tcpdatalen,mytcp + (mytcp->doff*4));
         */
      
      
          return checksum(tcp,totaltcp_len);
      
      }
      
      
      static u_int16_t tcp_checksum(struct iphdr* iphdrp){
          struct tcphdr *tcphdrp =
                  (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
                  return get_tcp_checksum(iphdrp, tcphdrp);
      }
      
      static void set_tcp_checksum(struct iphdr* iphdrp){
          struct tcphdr *tcphdrp =
                  (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
                  tcphdrp->check = 0;
                  tcphdrp->check = get_tcp_checksum(iphdrp, tcphdrp);
      }
      /****************************tcp checksum end****************************/
      
      
      /********************************Ip checksum*****************************/
      static u_int16_t ip_checksum(struct iphdr* iphdrp){
          return checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);
      }
      
      static void set_ip_checksum(struct iphdr* iphdrp){
          iphdrp->check = 0;
          iphdrp->check = checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);
      }
      /****************************Ip checksum end******************************/
      
      
      static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
                struct nfq_data *nfa, void *data)
      {
          int id = 0;
          struct nfqnl_msg_packet_hdr *ph;
          int pdata_len;
          unsigned char *payload;
      
          printf("entering callback\n");
          ph = nfq_get_msg_packet_hdr(nfa);
          if (ph) {
              id = ntohl(ph->packet_id);
          }
      
          pdata_len = nfq_get_payload(nfa, &payload);
          if (pdata_len >= 0) {
              struct iphdr *iphdrp = (struct iphdr*)payload;
              iphdrp->daddr = inet_addr(NAT_TO);
              set_ip_checksum(iphdrp);
              if(iphdrp->protocol == IPPROTO_TCP){
                  set_tcp_checksum(iphdrp);
                  printf(" ipsum+ %hu tcpsum+ %hu",
                         ip_checksum(iphdrp), tcp_checksum(iphdrp));
              }
              printf("len %d iphdr %d %u.%u.%u.%u ->",
                     pdata_len,
                     iphdrp->ihl<<2,
                     IPQUAD(iphdrp->saddr));
              printf(" %u.%u.%u.%u",
                     IPQUAD(iphdrp->daddr));
              printf(" ipsum %hu", ip_checksum(iphdrp));
              if(iphdrp->protocol == IPPROTO_TCP){
                  printf(" tcpsum %hu", tcp_checksum(iphdrp));
              }
              printf("\n");
      
          }
          return nfq_set_verdict(qh, id, NF_ACCEPT, (u_int32_t)pdata_len, payload);
      }
      
      int main(int argc, char **argv)
      {
          struct nfq_handle *h;
          struct nfq_q_handle *qh;
          struct nfnl_handle *nh;
          int fd;
          int rv;
          char buf[4096] __attribute__ ((aligned));
      
          printf("opening library handle\n");
          h = nfq_open();
          if (!h) {
              fprintf(stderr, "error during nfq_open()\n");
              exit(1);
          }
      
          printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
          if (nfq_unbind_pf(h, AF_INET) < 0) {
              fprintf(stderr, "error during nfq_unbind_pf()\n");
              exit(1);
          }
      
          printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
          if (nfq_bind_pf(h, AF_INET) < 0) {
              fprintf(stderr, "error during nfq_bind_pf()\n");
              exit(1);
          }
      
          printf("binding this socket to queue '0'\n");
          qh = nfq_create_queue(h,  0, &cb, NULL);
          if (!qh) {
              fprintf(stderr, "error during nfq_create_queue()\n");
              exit(1);
          }
      
          printf("setting copy_packet mode\n");
          if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
              fprintf(stderr, "can't set packet_copy mode\n");
              exit(1);
          }
      
          fd = nfq_fd(h);
      
          for (;;) {
              if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
                  printf("pkt received\n");
                  nfq_handle_packet(h, buf, rv);
                  continue;
              }
              /* if your application is too slow to digest the packets that
               * are sent from kernel-space, the socket buffer that we use
               * to enqueue packets may fill up returning ENOBUFS. Depending
               * on your application, this error may be ignored. Please, see
               * the doxygen documentation of this library on how to improve
               * this situation.
               */
              if (rv < 0 && errno == ENOBUFS) {
                  printf("losing packets!\n");
                  continue;
              }
              perror("recv failed");
              break;
          }
      
          printf("unbinding from queue 0\n");
          nfq_destroy_queue(qh);
      
      #ifdef INSANE
          /* normally, applications SHOULD NOT issue this command, since
           * it detaches other programs/sockets from AF_INET, too ! */
          printf("unbinding from AF_INET\n");
          nfq_unbind_pf(h, AF_INET);
      #endif
      
          printf("closing library handle\n");
          nfq_close(h);
      
          exit(0);
      }
      

      【讨论】:

        【解决方案5】:

        “itables”可执行文件存在于 Android 源代码中。内核也应该支持它。尽管您可能需要设备上的 root 权限才能使用它。

        【讨论】:

          【解决方案6】:

          我认为 iptables 在正常的 Android 发行版中不可用。但是,在 root 手机上,您可以添加交叉编译的 iptables 二进制文件。

          【讨论】:

          • 如何创建交叉编译的 iptables 二进制文件以及如何使用它?
          • 谢谢大家!我通过编译整个 android 源代码来编译 iptables 二进制文件。我根据博客“随机排序”做了一些更改,效果很好。
          • 嗨 Preetam 你能告诉我你做了什么改变让 iptables 像randomizedsort.blogspot.de/2011/03/…发布的那样工作
          • 我有 msm 内核 2.6.35,我正在努力在上面编译 iptables 1.4.10。内核已经有 iptables 1.3.7,我复制了博客中给出的 Android.mk。请帮忙
          猜你喜欢
          • 1970-01-01
          • 2012-10-09
          • 1970-01-01
          • 1970-01-01
          • 2011-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多