Iptables в android

Являются ли IPtables встроенными в ядро ​​Android? Если да, то как их использовать в нашем андроидном приложении?

Ответ 1

iptables - это модуль по умолчанию в AOSP, вы можете использовать netfilter для записи c-кода для его обработки.

Например, вы можете создать проект android и написать JNI файл, использовать ndk-build для его компиляции, а затем adb нажать исполняемый файл для файловой системы Android для выполнения. И в мобильной версии вы можете использовать оболочку для нее, напрямую используйте команду iptables в качестве пользователя root, как в 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);
}

Ответ 2

  • iptables доступен в дистрибутиве Android. Однако эта версия работает только с устройствами, построенными с ядром Linux 2.6.29.
  • Пользователи розничных устройств Android не могут получить доступ к двоичному файлу iptables. Даже сама ОС Android не может получить доступ к этому двоичному файлу. Это жестко закодировано в Android. Многие устройства также не имеют iptables.
  • Единственный способ доступа к двоичному файлу 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.

Ответ 3

Я не думаю, что iptables доступен в обычной дистрибутиве Android. Однако на корневом телефоне вы можете добавить кросс-скомпилированный двоичный файл iptables.

Ответ 4

Исполняемый файл "itables" присутствует в исходном коде Android. Ядро также должно его поддерживать. Хотя вам, вероятно, понадобятся права root на вашем устройстве, чтобы поиграть с ним.

Ответ 5

Это - это 5-летнее решение (требуется корень):

  • установите APK Android WiFi Tether из http://code.google.com/p/android-wifi-tether/
  • запустите терминал:

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

Но поскольку Google Code стал доступен только для чтения, он будет продолжать работать как обычно до "по крайней мере в январе 2016 года", это означает, что в следующем месяце этот ответ может оказаться бесполезным.

Ответ 6

с корневым телефоном, попробуйте использовать busybox и терминал для запуска "iptables -L" для отображения текущих таблиц. Я обнаружил, что все, что мне нужно было сделать, это root мой телефон и Iptables на моем другом розничном Android. как только устройство подтвердит iptables, вы можете использовать командную строку через приложение для настройки таблиц.