web-dev-qa-db-fra.com

iptables dans android

Les IPtables sont-ils intégrés dans le noyau Android? Si tel est le cas, comment les utiliser dans notre application Android?

32
Preetam

iptables est un module par défaut dans AOSP, vous pouvez utiliser netfilter pour écrire du code c pour gérer cela.

Par exemple, vous pouvez créer un projet Android, et écrire un fichier JNI, utiliser ndk-build pour le compiler, puis adb Poussez l'exécutable vers le Android = système de fichiers à exécuter. Et du côté mobile, vous pouvez y ajouter Shell, utiliser directement la commande iptables en tant qu'utilisateur root, tout comme sous Linux.

attachement:

#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);
}
10
ytliu
  1. iptables est disponible dans Android. Cette version ne fonctionne cependant qu'avec les appareils construits avec le noyau Linux 2.6.29.
  2. Les utilisateurs des détaillants Android ne peuvent pas accéder au binaire iptables. Même Android le système d'exploitation lui-même ne peut pas accéder à ce binaire. Il est codé en dur dans Android. De nombreux appareils ne le font pas non plus). t pas du tout iptables.
  3. La seule façon d'accéder au binaire iptables est de créer vos propres images Android. Consultez http://randomizedsort.blogspot.com/2010/08/building-Android-and- linux-kernel-for.html . Une fois que vous vous serez familiarisé avec ce processus, consultez http://randomizedsort.blogspot.com/2011/03/porting-iptables-1410-to-Android.html .
18
Nehc

Je ne pense pas que iptables soit disponible dans la distribution normale Android. Sur un téléphone enraciné, cependant, vous pouvez ajouter un binaire iptables compilé de manière croisée.

3
Prashast

avec un téléphone rooté, essayez d'utiliser la boîte occupée et le terminal pour exécuter "iptables -L" pour lister les tables actuelles. J'ai trouvé que tout ce que j'avais à faire était de rooter mon téléphone et j'avais des Iptables sur mon Android autrement vendu au détail. une fois que l'appareil a confirmé iptables, vous pouvez utiliser la ligne de commande via votre application pour ajuster les tables.

1
Hounge

L'exécutable "itables" est présent dans la source Android. Le noyau devrait également le prendre en charge. Bien que vous ayez probablement besoin des privilèges root sur votre appareil pour jouer avec.

1
mdc

This est une solution vieille de 5 ans (root requis):

Mais comme Google Code est devenu en lecture seule, il continuera de fonctionner normalement jusqu'au "janvier 2016 au moins", ce qui signifie que le mois prochain, cette réponse pourrait être inutile.

1
Leo