2011-01-02 20 views
24

IPtables có sẵn trong hạt nhân Android không? Nếu họ đang có, làm thế nào để sử dụng chúng trong ứng dụng Android của chúng tôi?iptables trong android

+1

Bạn đang cố gắng làm gì? Tôi sẽ không lộn xộn với các thiết lập iptables (nếu bạn thậm chí có thể). Nghe có vẻ độc hại. – Falmarri

+0

Tôi đang viết một tường lửa nhỏ như ứng dụng để hạn chế một số trang web. bây giờ, theo một câu trả lời tôi nhận được, tôi sẽ phải tạo ra nhị phân iptables, làm thế nào tôi có thể làm điều này (làm thế nào để tạo ra nhị phân iptables). sau đó tôi có thể phải sử dụng nó và chỉnh sửa một số quy tắc. – Preetam

+0

hi Preetam !!! Tôi cũng giống như vậy, để tạo một tường lửa bằng iptables !! bạn sẽ vui lòng cho tôi biết cách bạn quản lý để làm điều đó – Neji

Trả lời

8

iptables là mô-đun mặc định trong AOSP, bạn có thể sử dụng netfilter để viết mã c để xử lý. Ví dụ, bạn có thể tạo một dự án android và viết một tệp JNI, sử dụng ndk-build để biên dịch nó, và sau đó adb đẩy tệp thi hành vào hệ thống tệp android để thực thi. Và cuối cùng, bạn có thể adb shell vào nó, trực tiếp sử dụng lệnh iptables như một người dùng root, giống như trong linux.

tập tin đính kèm:

#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); 
} 
3

Tôi không nghĩ rằng iptables khả dụng trong bản phân phối Android thông thường. Tuy nhiên, trên một điện thoại bắt nguồn từ, bạn có thể thêm một nhị phân iptables được biên dịch chéo.

+0

cách tạo một nhị phân iptables được biên dịch chéo và làm thế nào tôi có thể sử dụng nó? – Preetam

+0

Kiểm tra chủ đề này - http://groups.google.com/group/android-developers/browse_thread/thread/29eaa212da14a80f?pli=1 – Prashast

+0

cảm ơn tất cả mọi người! tôi biên dịch iptables nhị phân bằng cách biên dịch toàn bộ nguồn Android. Tôi đã thực hiện một số thay đổi theo blog "Phân loại ngẫu nhiên" và nó đã hoạt động. – Preetam

1

Tệp thi hành "có thể thực hiện" có trong nguồn Android. Hạt nhân cũng nên hỗ trợ nó. Mặc dù bạn có thể sẽ cần quyền root trên thiết bị của bạn để chơi với nó.

17
  1. iptables khả dụng trong phân phối nguồn Android. Tuy nhiên phiên bản đó chỉ hoạt động với các thiết bị được xây dựng với hạt nhân Linux 2.6.29.
  2. Người dùng thiết bị Android bán lẻ không thể truy cập nhị phân iptables. Ngay cả hệ điều hành Android cũng không thể truy cập vào nhị phân đó. Điều này được mã hóa cứng trong Android. Nhiều thiết bị cũng không có iptables.
  3. Cách duy nhất để truy cập nhị phân iptables là tạo hình ảnh Android của riêng bạn. Kiểm tra http://randomizedsort.blogspot.com/2010/08/building-android-and-linux-kernel-for.html. Khi bạn thấy thoải mái với quy trình đó, hãy xem http://randomizedsort.blogspot.com/2011/03/porting-iptables-1410-to-android.html.
+0

cảm ơn bạn rất nhiều! Trên thực tế tôi đã biên soạn hình ảnh Android của riêng tôi (zImage), nhưng tôi nhận được lỗi trong khi tải nó trong trình mô phỏng. hãy kiểm tra liên kết này http://stackoverflow.com/questions/5406549/error-while-loading-new-compiled-linux-kernel-image-into-the-android-emulator1-5 – Preetam

+2

Điều đó không còn đúng, trên mọi ICS + Tôi đã thử gần đây hae hỗ trợ netfilter, do đó iptables nhị phân có thể cài đặt và sử dụng như là, cho thiết bị được bắt nguồn từ rõ ràng. – 3c71

0

với một chiếc điện thoại bắt nguồn từ, hãy thử sử dụng busybox và thiết bị đầu cuối để chạy "iptables -L" để liệt kê bảng hiện tại. Tôi thấy rằng tất cả những gì tôi phải làm là root điện thoại của tôi và có Iptables trên android bán lẻ của tôi. một khi thiết bị đã xác nhận iptables bạn có thể sử dụng dòng lệnh thông qua ứng dụng của bạn để điều chỉnh các bảng.

1

This là một giải pháp 5 tuổi (root bắt buộc):

  • cài đặt APK của Android WiFi Tether từ http://code.google.com/p/android-wifi-tether/
  • chạy một thiết bị đầu cuối:

    $ su - 
    # mount -o remount,rw /system 
    # cp /data/data/android.tether/bin/iptables /system/bin/ 
    

Nhưng vì Google Code đã trở thành chỉ đọc sẽ tiếp tục hoạt động như bình thường cho đến "ít nhất là tháng 1 năm 2016", có nghĩa là tháng tới, câu trả lời này r có thể là vô ích.

Các vấn đề liên quan