iptables en android

est-ce que IPtables est intégré dans le noyau android? Si oui, comment les utiliser dans notre application android?

26
demandé sur Neji 2011-01-02 08:23:21

6 réponses

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 compiler cela, puis adb pousser l'exécutable vers le système de fichiers android pour exécuter. Et dans l'extrémité mobile, vous pouvez adb shell, directement utiliser la commande suivante en tant qu'utilisateur racine, tout comme dans linux.

pièce jointe:

#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);
}
9
répondu ytliu 2013-05-31 12:37:17
  1. iptables est disponible dans la distribution Source Android. Cette version ne fonctionne cependant qu'avec les périphériques construits avec le noyau Linux 2.6.29.
  2. les utilisateurs d'appareils Android au détail ne peuvent pas accéder au binaire iptables. Même Android OS lui-même ne peut pas accéder à ce binaire. C'est codé en dur dans Android. Beaucoup de périphériques n'ont pas iptables.
  3. la seule façon d'accéder au binaire iptables est de construire vos propres images Android. Découvrez http://randomizedsort.blogspot.com/2010/08/building-android-and-linux-kernel-for.html. Une fois que vous êtes à l'aise avec ce processus, vérifier http://randomizedsort.blogspot.com/2011/03/porting-iptables-1410-to-android.html.
18
répondu Nehc 2017-09-02 05:07:26

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

3
répondu Prashast 2011-01-02 06:55:23

l'exécutable" itables " est présent dans la source Android. Le Noyau devrait également soutenir. Bien que vous aurez probablement besoin des privilèges de root sur votre appareil pour jouer avec.

1
répondu mdc 2011-01-17 13:41:13

à 5 ans de solution (root requis):

mais comme Google Code est devenu en lecture seule va continuer à fonctionner comme d'habitude jusqu'à "au moins janvier 2016", cela signifie que le mois prochain cette réponse pourrait être inutile.

1
répondu Leo 2015-12-29 13:58:27

avec un téléphone enraciné, essayez d'utiliser busybox et terminal pour exécuter "iptables-L" pour lister les tables courantes. J'ai trouvé que tout ce que j'avais à faire était de root mon téléphone et avait Iptables sur mon android autrement au détail. une fois que le périphérique a confirmé iptables, vous pouvez utiliser la ligne de commande via votre application pour ajuster les tables.

0
répondu Hounge 2013-10-24 06:50:49